Asm994a TMS99000 Assembler - v3.010 * Asm994a Generated Register Equates * 0000 0000 R0 EQU 0 0000 0001 R1 EQU 1 0000 0002 R2 EQU 2 0000 0003 R3 EQU 3 0000 0004 R4 EQU 4 0000 0005 R5 EQU 5 0000 0006 R6 EQU 6 0000 0007 R7 EQU 7 0000 0008 R8 EQU 8 0000 0009 R9 EQU 9 0000 000A R10 EQU 10 0000 000B R11 EQU 11 0000 000C R12 EQU 12 0000 000D R13 EQU 13 0000 000E R14 EQU 14 0000 000F R15 EQU 15 * 1 ; _____ _ _____ _ _ 2 ; |_ _|_ _ _ __| |__ ___ | ___|___ _ __| |_| |__ 3 ; | | | | | | '__| '_ \ / _ \| |_ / _ \| '__| __| '_ \ 4 ; | | | |_| | | | |_) | (_) | _|| (_) | | | |_| | | | 5 ; |_| \__,_|_| |_.__/ \___/|_| \___/|_| \__|_| |_| 6 ; ################################################ 7 ; TurboForth 8 ; (C) Mark Wills 2009-2012 9 ; Written in TMS9900 machine code for the TI-99/4A 10 ; May the Forth be with you. 11 ; ################################################ 12 ; ____ _ ___ 13 ; | __ ) __ _ _ __ | | __ / _ \ 14 ; | _ \ / _` | '_ \| |/ / | | | | 15 ; | |_) | (_| | | | | < | |_| | 16 ; |____/ \__,_|_| |_|_|\_\ \___/ 17 ; 18 ; This is bank 0 - the main bank, containing: 19 ; Forth dictionary 20 ; Any words written in Forth 21 ; Console routines (keyboard, scrolling, cursor etc) 22 ; 23 ; Due to memory contraints, some dictionary entries are stub entries 24 ; containing only the dictionary entry and a call into bank 1 where the 25 ; main code resides. I have tried to keep routines that need to run quickly 26 ; (i.e. without the overhead of a bank-switch/branch and bank-switch/return 27 ; in this bank. 28 29 ; _ _ _ 30 ; | | | | | | 31 ; | |__| | ___ __ _ __| | ___ _ __ 32 ; | __ |/ _ \/ _` |/ _` |/ _ \ '__| 33 ; | | | | __/ (_| | (_| | __/ | 34 ; |_| |_|\___|\__,_|\__,_|\___|_| 35 36 aorg >6000 ; cartridge rom 37 38 ; cartridge ROM header 39 40 6000 AA byte >aa ; standard header 41 6001 0C byte >0c ; version number 42 6002 01 byte >01 ; number of programs 43 6003 00 byte >00 ; not used 44 6004 0000 data >0000 ; pointer to power-up list 45 6006 600C data menu ; pointer to program list 46 6008 0000 data 0 ; pointer to DSRL list 47 600A 0000 data 0 ; pointer to subprogram list 48 49 600C 6026 menu data menu40 ; pointer to next menu item 50 600E 605C data start80 ; code entry point 51 6010 14 byte 20 ; length of text 52 6011 5455 text 'TURBOFORTH 80 COLUMN' 52 6013 5242 52 6015 4F46 52 6017 4F52 52 6019 5448 52 601B 2038 52 601D 3020 52 601F 434F 52 6021 4C55 52 6023 4D4E 53 6025 0000 even 54 6026 0000 menu40 data 0 ; no more menu entries 55 6028 6052 data start40 ; code entry point (see 0-01-Startup.a99) 56 602A 11 byte 17 ; length of text 57 602B 5455 mtext text 'TURBOFORTH V1.2.1:1 (c) 2015 Mark Wills' 57 602D 5242 57 602F 4F46 57 6031 4F52 57 6033 5448 57 6035 2056 57 6037 312E 57 6039 322E 57 603B 313A 57 603D 3120 57 603F 2863 57 6041 2920 57 6043 3230 57 6045 3135 57 6047 204D 57 6049 6172 57 604B 6B20 57 604D 5769 57 604F 6C6C 57 6051 73 58 even 59 60 ; 40 column mode entry point 61 6052 02E0 start40 lwpi wkspc 61 6054 8300 62 6056 04E0 clr @sumode 62 6058 A078 63 605A 1009 jmp startB0 ; defined in 0-01-Startup.a99 64 65 ; 80 column mode entry point 66 605C 02E0 start80 lwpi wkspc 66 605E 8300 67 6060 0200 li r0,2 67 6062 0002 68 6064 C800 mov r0,@sumode 68 6066 A078 69 6068 1002 jmp startB0 ; defined in 0-01-Startup.a99 70 71 ; codes for bank 0 and bank 1 - used by the interrupt handler to determine which 72 ; bank to return to after processing an interrupt. 73 ; Set by the VDP routines (see 0-22-VDP.a99) 74 ; DO NOT MOVE THESE! Identical definitions are made in bank 1, and they MUST 75 ; be at identical addresses! 76 606A 6002 bank0 data >6002 ; code to select bank 0 77 606C 6000 bank1_ data >6000 ; code to select bank 1 78 79 80 ; General Equates 81 0000 8300 wkspc equ >8300 ; workspace pointer 82 0000 0000 link equ 0 ; chain of links 83 0000 837C gplst equ >837c ; gpl status byte 84 0000 8375 keyin equ >8375 ; location of ascii key pressed (via KSCAN) 85 0000 009D quitky equ 157 ; key code for cold reset (157=CTRL and =) 86 0000 834A fac equ >834a ; FAC 87 0000 83C4 ISR equ >83c4 ; address of isr hook 88 89 0000 0003 pc equ r3 ; friendly name for program counter register 90 0000 0004 stack equ r4 ; friendly name for data stack register 91 0000 0005 rstack equ r5 ; friendly name for return stack register 92 0000 000C NEXT equ r12 ; friendly name for NEXT routine 93 94 0000 8000 immed equ >8000 ; flag for immediate words * * COPY 'C:\TI\Source\TurboForth\Bank0\0-01-Startup.a99' * 1 ; _____ _ _ 2 ; / ____| | | | 3 ; | (___ | |_ __ _ _ __| |_ _ _ _ __ 4 ; \___ \| __|/ _` | '__| __| | | | '_ \ 5 ; ____) | |_| (_| | | | |_| |_| | |_) | 6 ; |_____/ \__|\__,_|_| \__|\__,_| .__/ 7 ; | | 8 ; |_| 9 ; STARTUP - general initialisation code for bank 0 10 ; and a few high level Forth kernal words for starting 11 ; the interpreter, cold starting, etc 12 13 ;[ START 14 606E 0300 startB0 limi 0 ; no interrupts thank-you, we're British 14 6070 0000 15 16 6072 04E0 clr @>6000 ; we're now in bank 1 16 6074 6000 17 ; note, bank 1 has identical code at these addresses so we 18 ; can safely bank switch 19 6076 0460 b @init ; init is defined in 1-15-Initialise.a99 19 6078 7B76 20 21 607A 020C afteri li r12,_next ; we'll use r12 as a pointer to NEXT 21 607C 8326 22 607E 0203 li pc,cstart ; setup Forth instruction pointer (R3) 22 6080 60D4 23 6082 045C b *r12 ; call NEXT (start execution) 24 ; from this point we're actually running in forth 25 ;] 26 27 ; pc = instruction pointer (R3) 28 ; stack = data stack pointer (R4) 29 ; rstack = return stack pointer (R5) 30 31 ;[ space saving routines... these replace common phrases found in the source 32 ; The following four routines save 2 bytes each time they are used 33 6084 6086 lit0 data $+2 ; push 0 to stack 34 6086 0644 dect stack 35 6088 04D4 clr *stack 36 608A 045C b *next 37 38 608C 8320 lit1 data docol,lit,1,exit ; push 1 to stack 38 608E 70B2 38 6090 0001 38 6092 832C 39 6094 8320 lit8 data docol,lit,8,exit ; push 8 to stack 39 6096 70B2 39 6098 0008 39 609A 832C 40 41 609C 609E litm1 data $+2 ; push -1 to stack 42 609E 0644 dect stack 43 60A0 0714 seto *stack 44 60A2 045C b *next 45 46 ; another common phrase is COMPILE BRANCH 47 60A4 8320 combra data docol,compile,branch,exit 47 60A6 7262 47 60A8 65E4 47 60AA 832C 48 49 ; COMPILE LIT COMMA 50 60AC 8320 clc data docol,compile,lit,comma,exit 50 60AE 7262 50 60B0 70B2 50 60B2 70CC 50 60B4 832C 51 52 ; Alternative to TYPE. A typical phrase is LITLIT 53 ; This routine allows the above phrase to be replaced with TOTERMTYPE 54 ; Saving 4 bytes each time it is used. Net saving ~80 bytes. 55 60B6 8320 toterm data docol,term1,type,exit 55 60B8 60BE 55 60BA 6C94 55 60BC 832C 56 60BE 60C0 term1 data $+2 57 60C0 C055 mov *rstack,r1 ; get address of address of text 58 60C2 C0A1 mov @2(r1),r2 ; get length of text 58 60C4 0002 59 60C6 0644 dect stack ; create stack entry 60 60C8 C511 mov *r1,*stack ; push address 61 60CA 0644 dect stack ; create stack entry 62 60CC C502 mov r2,*stack ; push length 63 ; change the address on the return stack to move past 64 ; the text address and text length, which are in-line... 65 60CE 05D5 inct *rstack ; move past address 66 60D0 05D5 inct *rstack ; move past length 67 60D2 045C b *next 68 ;] 69 70 ;[ COLD START 71 ; This routine is called when the system starts for the first time. 72 60D4 60D6 cstart data bootup 73 60D6 8320 bootup data docol,synth ; check if speech synth is fitted 73 60D8 60FE 74 ; the graphics mode is loaded by the cart startup menus 75 60DA 70B2 data lit,sumode,fetch,gmode ; set appropriate graphics mode 75 60DC A078 75 60DE 6830 75 60E0 795E 76 60E2 60B6 data toterm,mtext,39,cr ; type title to screen 76 60E4 602B 76 60E6 0027 76 60E8 6E92 77 60EA 6E62 data keyq,cboot ; scan keyboard and call cboot 77 60EC 6106 78 60EE 65F6 data zbrnch,skipld ; skip bootloader if enter key was pressed 78 60F0 60FC 79 60F2 608C data lit1,load ; boot from disk - load block 1 79 60F4 7C18 80 60F6 70B2 data lit,doboot,store0 ; reset booting flag 80 60F8 A04E 80 60FA 6892 81 60FC 7464 skipld data ab0rt ; call QUIT. 82 60FE 6100 synth data $+2 ; check if speech synth is fitted 83 6100 06A0 bl @bank1 83 6102 8332 84 6104 6684 data isspch ; see 1-05-speech.a99 85 86 ; permit booting from DSKx where x is any ASCII character 87 ; To boot from something other than DSK1 just hold down the appropriate key at 88 ; boot-time. 89 6106 6108 cboot data $+2 90 6108 06A0 bl @bank1 90 610A 8332 91 610C 7E9C data _cboot ; defined in 1-15-Initialise.a99 92 ;] 93 94 ;[ EXIT -- C,79 95 ; Compiled within a colon definition such that when executed, that colon 96 ; definition returns control to the definition that passed control to it by 97 ; returning control to the return point on the top of the return stack. 98 ; An error condition exists if the top of the return stack does not contain a 99 ; valid return point. 100 ; See: ; "stack, return" "9.3 Return Stack" 101 ; 102 ; Note: This word is the last word in the dictionary. Consequently it's link 103 ; field has a value of 0. FIND uses this to determine if it has searched every 104 ; word in the dictionary. 105 610E 0000 exith data 0,4 105 6110 0004 106 6112 4558 text 'EXIT' 106 6114 4954 107 6116 6118 exitt data $+2 108 6118 0460 b @exit+2 108 611A 832E 109 ;] 110 111 ;[ QUIT -- 79 112 ; Clears the return stack, sets interpret state, accepts new input from the 113 ; current input device, and begins text interpretation. No message is 114 ; displayed. 115 611C 610E quith data exith,4 115 611E 0004 116 6120 5155 text 'QUIT' 116 6122 4954 117 6124 8320 quit data docol 118 6126 70B2 quitlp data lit,>0500,lit,keydev,store ; set keyscan code 118 6128 0500 118 612A 70B2 118 612C A022 118 612E 6852 119 6130 6154 data rrstack ; reset return stack 120 6132 773E data tib_,fetch,lit,80,expect ; get some input 120 6134 6830 120 6136 70B2 120 6138 0050 120 613A 69D2 121 ; data ghere,lit,80,expect 122 613C 72FE data interp ; call INTERPRET 123 613E 73CC data stkuf ; check for stack underflow 124 6140 60B6 data toterm,oktxt,3 ; type OK 124 6142 6150 124 6144 0003 125 6146 6240 data depth,dot,cr ; display stack depth 125 6148 783C 125 614A 6E92 126 614C 65E4 data branch,quitlp ; repeat endlessly 126 614E 6126 127 6150 6F6B oktxt text 'ok:' 127 6152 3A 128 6153 0000 even 129 6154 6156 rrstack data $+2 130 6156 0205 li rstack,retstk ; reset return stack pointer 130 6158 A28A 131 615A 045C b *next 132 ;] 133 134 ;[ COLD ( -- ) 135 ; performs a cold reset of the system 136 615C 611C coldh data quith,4 136 615E 0004 137 6160 434F text 'COLD' 137 6162 4C44 138 6164 6166 data $+2 139 6166 0460 cold b @startB0 ; restart the whole shebang 139 6168 606E 140 ;] * * COPY 'C:\TI\Source\TurboForth\Bank0\0-02-Stack.a99' * 1 ; _____ _ _ __ __ _ 2 ; / ____| | | | \ \ / / | | 3 ; | (___ | |_ __ _ ___| | __ \ \ /\ / /___ _ __ __| |___ 4 ; \___ \| __|/ _` |/ __| |/ / \ \/ \/ // _ \| '__/ _` / __| 5 ; ____) | |_| (_| | (__| < \ /\ /| (_) | | | (_| \__ \ 6 ; |_____/ \__|\__,_|\___|_|\_\ \/ \/ \___/|_| \__,_|___/ 7 ; Core words pertaining to data and return stack manipulation 8 9 10 ;[ DROP 16b -- 79 11 ; 16b is removed from the stack. 12 616A 615C droph data coldh,4 ; link to previous word and length of word 12 616C 0004 13 616E 4452 text 'DROP' ; name of word 13 6170 4F50 14 6172 838A drop data _drop ; code is in high-speed ram. 15 ; see 1-15-Initialise.a99 16 ;] 17 18 ;[ SWAP 16b1 16b2 -- 16b2 16b1 79 19 ; The top two stack entries are exchanged. 20 6174 616A swaph data droph,4 20 6176 0004 21 6178 5357 text 'SWAP' 21 617A 4150 22 617C 835C swap data _swap ; code is in high-speed ram. 23 ; see 1-15-Initialise.a99 24 ;] 25 26 ;[ DUP 16b -- 16b 16b 79 "dupe" 27 ; Duplicate 16b. 28 617E 6174 duph data swaph,3 28 6180 0003 29 6182 4455 text 'DUP ' 29 6184 5020 30 6186 8382 dup data _dup ; code is in high-speed ram. 31 ; see 1-15-Initialise.a99 32 ;] 33 34 ;[ ROT 16b1 16b2 16b3 -- 16b2 16b3 16b1 79 "rote" 35 ; The top three stack entries are rotated, bringing the deepest to the top. 36 6188 617E roth data duph,3 36 618A 0003 37 618C 524F text 'ROT ' 37 618E 5420 38 6190 6192 rot data $+2 39 6192 C1A4 mov @4(stack),r6 ; save x1 39 6194 0004 40 6196 C924 mov @2(stack),@4(stack) ; move x2 backwards on stack 40 6198 0002 40 619A 0004 41 619C C914 mov *stack,@2(stack) ; move x3 bacwards on stack 41 619E 0002 42 61A0 C506 mov r6,*stack ; put x1 on top of stack 43 61A2 045C b *next 44 ;] 45 46 ;[ -ROT 16b1 16b2 16b3 -- 16b3 16b1 16b2 47 ; The top three stack entries are rotated, sending the top item to the deepest 48 ; poisition 49 61A4 6188 nroth data roth,4 49 61A6 0004 50 61A8 2D52 text '-ROT' 50 61AA 4F54 51 61AC 61AE nrot data $+2 52 61AE C194 mov *stack,r6 ; save x3 53 61B0 C524 mov @2(stack),*stack ; move x2 forwards on stack 53 61B2 0002 54 61B4 C924 mov @4(stack),@2(stack) ; move x1 forwards on stack 54 61B6 0004 54 61B8 0002 55 61BA C906 mov r6,@4(stack) ; put x3 on bottom 55 61BC 0004 56 61BE 045C b *next 57 ;] 58 59 ;[ OVER 16b1 16b2 -- 16b1 16b2 16b3 79 60 ; 16b3 is a copy of 16b1. 61 61C0 61A4 overh data nroth,4 61 61C2 0004 62 61C4 4F56 text 'OVER' 62 61C6 4552 63 61C8 838E over data _over ; code is in high-speed ram. 64 ; see 1-15-Initialise.a99 65 ;] 66 67 ;[ NIP 16b1 16b2 -- 16b2 68 ; 16b1 is removed from the stack 69 61CA 61C0 niph data overh,3 69 61CC 0003 70 61CE 4E49 text 'NIP ' 70 61D0 5020 71 61D2 61D4 nip data $+2 72 61D4 C534 mov *stack+,*stack ; copy 16b2 and perform pop 73 61D6 045C b *next 74 ;] 75 76 ;[ TUCK 16b1 16b2 -- 16b2 16b1 16b2 77 ; places a copy of 16b2 at the third data stack position. 78 ; 16b1 and 16b2 move upwards. 79 61D8 61CA tuckh data niph,4 79 61DA 0004 80 61DC 5455 text 'TUCK' 80 61DE 434B 81 61E0 61E2 tuck data $+2 82 61E2 0644 dect stack 83 61E4 C524 mov @2(stack),*stack 83 61E6 0002 84 61E8 C924 mov @4(stack),@2(stack) 84 61EA 0004 84 61EC 0002 85 61EE C914 mov *stack,@4(stack) 85 61F0 0004 86 61F2 045C b *next 87 ;] 88 89 ;[ ?DUP 16b -- 16b 16b 79 "question-dupe" 90 ; or: 0 -- 0. Duplicate 16b if it is non-zero. 91 61F4 61D8 dup0h data tuckh,4 91 61F6 0004 92 61F8 3F44 text '?DUP' 92 61FA 5550 93 61FC 61FE qdup data $+2 94 61FE C514 mov *stack,*stack ; set EQ bit in status register if TOS=0 95 6200 1303 jeq qdupx ; jump if TOS=0 and exit 96 6202 0644 dect stack ; create stack entry 97 6204 C524 mov @2(stack),*stack ; copy tos 97 6206 0002 98 6208 045C qdupx b *next 99 ;] 100 101 ;[ PICK +n -- 16b 83 102 ; 16b is a copy of the +nth stack value, not counting +n itself. 103 ; {0..the number of elements on stack-1} 104 ; 0 PICK is equivalent to DUP 105 ; 1 PICK is equivalent to OVER 106 620A 61F4 pickh data dup0h,4 106 620C 0004 107 620E 5049 text 'PICK' 107 6210 434B 108 6212 6214 pick data $+2 109 6214 06A0 bl @bank1 109 6216 8332 110 6218 78B8 data _pick 111 ;] 112 113 ;[ >< ( xy -- yx ) 114 ; Swaps bytes in the top data stack cell. For example $1234 becomes $3412 115 621A 620A swpbh data pickh,2 115 621C 0002 116 621E 3E3C text '><' 117 6220 6222 swpb_ data $+2 118 6222 06D4 swpb *stack ; swap bytes in TOS 119 6224 045C b *next 120 ;] 121 122 ;[ ROLL +n -- 83 123 ; The +nth stack value, not counting +n itself is first removed and then 124 ; transferred to the top of the stack, moving the remaining values into the 125 ; vacated position. 126 ; {0..the number of elements on the stack-1} 127 ; 2 ROLL is equivalent to ROT 128 ; 0 ROLL is a null operation 129 6226 621A rollh data swpbh,4 129 6228 0004 130 622A 524F text 'ROLL' 130 622C 4C4C 131 622E 6230 roll data $+2 132 6230 06A0 bl @bank1 132 6232 8332 133 6234 78C6 data _roll 134 ;] 135 136 ;[ DEPTH -- +n 79 137 ; +n is the number of 16-bit values contained in the data stack before +n was 138 ; placed on the stack. 139 6236 6226 depthh data rollh,5 139 6238 0005 140 623A 4445 text 'DEPTH ' 140 623C 5054 140 623E 4820 141 6240 6242 depth data $+2 142 6242 06A0 bl @bank1 142 6244 8332 143 6246 78E8 data _depth 144 ;] 145 146 ;[ .S ( -- ) 147 ; produce non-destructive stack dump to the screen. 148 6248 6236 ndsh data depthh,2 148 624A 0002 149 624C 2E53 text '.S' 150 624E 8320 dots data docol,depth,zbrnch,dotst 150 6250 6240 150 6252 65F6 150 6254 627C 151 6256 608C data lit1,depth,sub1 151 6258 6240 151 625A 62C2 152 625C 66F6 data do,dotst 152 625E 627C 153 6260 679A dots1 data geti,sub1,pick 153 6262 62C2 153 6264 6212 154 6266 7602 data usignd,fetch,zbrnch,dots3 154 6268 6830 154 626A 65F6 154 626C 6274 155 626E 782C data udot,branch,dots4 155 6270 65E4 155 6272 6276 156 6274 783C dots3 data dot 157 6276 609C dots4 data litm1 158 6278 6778 data ploop,dots1 158 627A 6260 159 627C 60B6 dotst data toterm,dottxt,5 159 627E 6284 159 6280 0005 160 6282 832C data exit 161 6284 3C54 dottxt text ' 161 6286 4F50 161 6288 2020 162 ;] 163 164 ; RETURN STACK WORDS: 165 166 ;[ >R 16b -- C,79 "to-r" 167 ; Transfers 16b to the return stack. 168 628A 6248 rspshh data ndsh,2 168 628C 0002 169 628E 3E52 text '>R' 170 6290 6292 rspush data $+2 171 6292 0645 dect rstack ; move return stack to the next position 172 6294 C574 mov *stack+,*rstack ; pop word on data stack to return stack 173 6296 045C b *next 174 ;] 175 176 ;[ R@ -- 16b C,79 "r-fetch" 177 ; 16b is a copy of the top of the return stack. 178 6298 628A rsch data rspshh,2 178 629A 0002 179 629C 5240 text 'R@' 180 629E 62A0 rsc data $+2 181 62A0 0644 dect stack ; move forward on data stack 182 62A2 C515 mov *rstack,*stack ; copy word from return stack to data stack 183 62A4 045C b *next 184 ;] 185 186 ;[ R> -- 16b C,79 "r-from" 187 ; 16b is removed from the return stack and transferred to the data stack. 188 62A6 6298 rspoph data rsch,2 188 62A8 0002 189 62AA 523E text 'R>' 190 62AC 62AE rspop data $+2 191 62AE 0644 dect stack ; move forward on data stack 192 62B0 C535 mov *rstack+,*stack ; pop top of return stack to data stack 193 62B2 045C b *next 194 ;] * * COPY 'C:\TI\Source\TurboForth\Bank0\0-03-Math.a99' * 1 ; __ __ _ _ __ __ _ 2 ; | \/ | | | | | \ \ / / | | 3 ; | \ / | __ _| |_| |__ \ \ /\ / /___ _ __ __| |___ 4 ; | |\/| |/ _` | __| '_ \ \ \/ \/ // _ \| '__/ _` / __| 5 ; | | | | (_| | |_| | | | \ /\ /| (_) | | | (_| \__ \ 6 ; |_| |_|\__,_|\__|_| |_| \/ \/ \___/|_| \__,_|___/ 7 8 9 ;[ 1+ w1 -- w2 79 "one-plus" 10 ; w2 is the result of adding one to w1 according to the operations of + 11 62B4 62A6 plus1h data rspoph,2 11 62B6 0002 12 62B8 312B text '1+' 13 62BA 8396 plus1 data _plus1 ; code is in high-speed ram. 14 ; see 1-15-Initialise.a99 15 ;] 16 17 ;[ 1- w1 -- w2 79 "one-minus" 18 ; w2 is the result of subtracting one from w1 according to the operation of - 19 62BC 62B4 sub1h data plus1h,2 19 62BE 0002 20 62C0 312D text '1-' 21 62C2 62C4 sub1 data $+2 22 62C4 0614 dec *stack 23 62C6 045C b *next 24 ;] 25 26 ;[ 2+ w1 -- w2 79 "two-plus" 27 ; w2 is the result of adding two to w1 according to the operation of + 28 62C8 62BC plus2h data sub1h,2 28 62CA 0002 29 62CC 322B text '2+' 30 62CE 839A plus2 data _plus2 ; code is in high-speed ram. 31 ; see 1-15-Initialise.a99 32 ;] 33 34 ;[ CELL+ w1 -- w2+2 35 ; adds two (the cell size) to top of stack 36 62D0 62C8 cellph data plus2h,5 36 62D2 0005 37 62D4 4345 text 'CELL+ ' 37 62D6 4C4C 37 62D8 2B20 38 62DA 839A cellp data _plus2 39 ;] 40 41 ;[ CHAR+ w1 -- w2+2 42 ; adds two (the cell size) to top of stack 43 62DC 62D0 charph data cellph,5 43 62DE 0005 44 62E0 4348 text 'CHAR+ ' 44 62E2 4152 44 62E4 2B20 45 62E6 8396 charp data _plus1 46 ;] 47 48 ;[ 2- w1 -- w2 79 "two-minus" 49 ; w2 is the result of subtracting two from w1 according to the operation of - 50 62E8 62DC sub2h data charph,2 50 62EA 0002 51 62EC 322D text '2-' 52 62EE 839E sub2 data _sub2 ; code is in high-speed ram. 53 ; see 1-15-Initialise.a99 54 ;] 55 56 ;[ 2* ( x -- x<<1 ) 57 ; shifts the value on the stack left by one bit. 58 62F0 62E8 mul2h data sub2h,2 58 62F2 0002 59 62F4 322A text '2*' 60 62F6 62F8 mul2 data $+2 61 62F8 A514 mul3 a *stack,*stack ; :-) 62 62FA 045C b *next 63 ;] 64 65 ;[ CELLS ( x1 -- x1*2 ) 66 ; returns the memory size required to hold x1 cells 67 62FC 62F0 cellsh data mul2h,5 67 62FE 0005 68 6300 4345 text 'CELLS ' 68 6302 4C4C 68 6304 5320 69 6306 62F8 cells data mul3 ; use the word 2* to do our work for us 70 ;] 71 72 ;[ 2/ n1 -- n2 83 "two-divide" 73 ; n2 is the result of arithmetically shifting n1 right one bit. 74 ; The sign is included in the shift and remains unchanged. 75 6308 62FC div2h data cellsh,2 75 630A 0002 76 630C 322F text '2/' 77 630E 6310 div2 data $+2 78 6310 C214 mov *stack,r8 ; TOS in r8 79 6312 0818 sra r8,1 ; shift right 80 6314 C508 mov r8,*stack ; store on stack 81 6316 045C b *next 82 ;] 83 84 ;[ + w1 w2 -- w3 79 "plus" 85 ; w3 is the arithmetic sum of w1 plus w2. 86 6318 6308 addh data div2h,1 86 631A 0001 87 631C 2B20 text '+ ' 88 631E 83A2 add data _add ; code is in high-speed ram. 89 ; see 1-15-Initialise.a99 90 ;] 91 92 ;[ - w1 w2 -- w3 79 "minus" 93 ; w3 is the result of subtracting w2 from w1. 94 6320 6318 subh data addh,1 94 6322 0001 95 6324 2D20 text '- ' 96 6326 83A6 sub data _sub ; code is in high-speed ram. 97 ; see 1-15-Initialise.a99 98 ;] 99 100 ;[ * w1 w2 -- w3 79 "times" 101 ; w3 is the least-significant 16 bits of the arithmetic product of w1 times w2. 102 6328 6320 mulh data subh,1 102 632A 0001 103 632C 2A20 text '* ' 104 632E 83AA mul data _mul ; code is in high-speed ram. 105 ; see 1-15-Initialise.a99 106 ;] 107 108 ;[ */ n1 n2 n3 -- n4 83 "times-divide" 109 ; n1 is first multiplied by n2 producing an intermediate 32-bit result. 110 ; n4 is the floor of the quotient of the intermediate 32-bit result divided by 111 ; the divisor n3. 112 ; The product of n1 times n2 is maintained as an intermediate 32-bit result for 113 ; greater precision than the otherwise equivalent sequence: n1 n2 * n3 / . 114 ; An error condition results if the divisor is zero or if the quotient falls 115 ; outside of the range {-32,768..32,767}. 116 6330 6328 sslash data mulh,2 116 6332 0002 117 6334 2A2F text '*/' 118 6336 8320 data docol 119 6338 6386 data ssm ; */MOD 120 633A 61D2 data nip ; discard remainder 121 633C 832C data exit 122 633E 045C b *next 123 ;] 124 125 ;[ UM* u1 u2 -- ud 83 "u-m-times" 126 ; ud is the unsigned-double product of u1 times u2. 127 ; All values and arithmetic are unsigned. 128 ; high word of ud to top of stack 129 6340 6330 umsh data sslash,3 129 6342 0003 130 6344 554D text 'UM* ' 130 6346 2A20 131 6348 634A data $+2 132 634A C014 mov *stack,r0 ; get u2 133 634C C064 mov @2(stack),r1 ; get r1 133 634E 0002 134 6350 3840 mpy r0,r1 ; perform unsigned multiply 135 6352 C501 mov r1,*stack ; push high word 136 6354 C902 mov r2,@2(stack) ; push low word 136 6356 0002 137 6358 045C b *next 138 ;] 139 140 ;[ /MOD n1 n2 -- n3 n4 83 "divide-mod" 141 ; n3 is the remainder and n4 the floor of the quotient of n1 divided by the 142 ; divisor n2. 143 ; n3 has the same sign as n2 or is zero. 144 ; An error condition results if the divisor is zero or if the quotient falls 145 ; outside of the range {-32,768..32,767}. 146 635A 6340 smodh data umsh,4 146 635C 0004 147 635E 2F4D text '/MOD' 147 6360 4F44 148 6362 6364 smod data $+2 149 6364 C014 mov *stack,r0 ; get n2 (divisor) 150 6366 0701 seto r1 ; dividend is 32-bit, assume negative 151 6368 C0A4 mov @2(stack),r2 ; get n1 (dividend) 151 636A 0002 152 636C 1101 jlt smod1 ; if negative then skip 153 636E 04C1 clr r1 ; otherwise it's positive. clear upper word 154 6370 06A0 smod1 bl @sidiv ; do a signed division 154 6372 6422 155 6374 C501 mov r1,*stack ; push quotient 156 6376 C902 mov r2,@2(stack) ; push remainder 156 6378 0002 157 637A 045C b *next 158 ;] 159 160 ;[ */MOD n1 n2 n3 -- n4 n5 83 "times-divide-mod" 161 ; n1 is first multiplied by n2 producing an intermediate 32-bit result. 162 ; n4 is the remainder and n5 is the floor of the quotient of the intermediate 163 ; 32-bit result divided by the divisor n3. A 32-bit intermediate product is 164 ; used as for */ . n4 has the same sign as n3 or is zero. An error condition 165 ; results if the divisor is zero or if the quotient falls outside of the range 166 ; {-32,768..32,767}. 167 637C 635A ssmh data smodh,5 167 637E 0005 168 6380 2A2F text '*/MOD ' 168 6382 4D4F 168 6384 4420 169 6386 6388 ssm data $+2 170 6388 C024 mov @2(stack),r0 ; get n2 170 638A 0002 171 638C C064 mov @4(stack),r1 ; get n1 171 638E 0004 172 6390 06A0 bl @simul ; signed multiply 172 6392 645C 173 6394 C034 mov *stack+,r0 ; pop n3 to r0 (divisor) 174 6396 06A0 bl @sidiv ; signed divide 174 6398 6422 175 639A C501 mov r1,*stack ; push quotient 176 639C C902 mov r2,@2(stack) ; push remainder 176 639E 0002 177 63A0 045C b *next 178 ;] 179 180 ;[ UM/MOD ud u1 -- u2 u3 83 "u-m-divide-mod" 181 ; u2 is the remainder and u3 is the floor of the quotient after dividing ud by 182 ; the divisor u1. All values and arithmetic are unsigned. An error condition 183 ; results if the divisor is zero or if the quotient lies outside the range 184 63A2 637C umodh data ssmh,6 184 63A4 0006 185 63A6 554D text 'UM/MOD' 185 63A8 2F4D 185 63AA 4F44 186 63AC 63AE usmod data $+2 187 63AE C034 mov *stack+,r0 ; pop u1 to r0 (divisor) 188 63B0 C054 mov *stack,r1 ; high word of ud to r1 189 63B2 C0A4 mov @2(stack),r2 ; low word of ud to r2 189 63B4 0002 190 63B6 3C40 div r0,r1 ; perform unsigned division 191 63B8 C501 mov r1,*stack ; push quotient 192 63BA C902 mov r2,@2(stack) ; push remainder 192 63BC 0002 193 63BE 045C b *next 194 ;] 195 196 ;[ / n1 n2 -- n3 83 "divide" 197 ; n3 is the floor of the quotient of n1 divided by the divisor n2. 198 ; An error condition results if the divisor is zero or if the quotient falls 199 ; outside of the range {-32,768..32,767}. 200 63C0 63A2 sdivh data umodh,1 200 63C2 0001 201 63C4 2F20 text '/ ' 202 63C6 8320 sdiv data docol,smod,nip,exit 202 63C8 6362 202 63CA 61D2 202 63CC 832C 203 ;] 204 205 ;[ MOD n1 n2 -- n3 83 206 ; n3 is the remainder after dividing n1 by the divisor n2. 207 ; n3 has the same sign as n2 or is zero. 208 ; An error condition results if the divisor is zero or if the quotient falls 209 ; outside of the range {-32,768..32,767}. 210 63CE 63C0 modh data sdivh,3 210 63D0 0003 211 63D2 4D4F text 'MOD ' 211 63D4 4420 212 63D6 8320 mod data docol,smod,drop,exit 212 63D8 6362 212 63DA 6172 212 63DC 832C 213 ;] 214 215 ;[ NEGATE n1 -- n2 79 216 ; n2 is the two's complement of n1, i.e, the difference of zero less n1. 217 63DE 63CE negh data modh,6 217 63E0 0006 218 63E2 4E45 text 'NEGATE' 218 63E4 4741 218 63E6 5445 219 63E8 63EA neg_ data $+2 220 63EA 0514 neg2 neg *stack ; negate the word on TOS 221 63EC 045C b *next 222 ;] 223 224 ;[ ABS n -- u 79 "absolute" 225 ; u is the absolute value of n. If n is -32,768 then u is the same value. 226 ; STATUS: TESTED OK 13 APR 2009 227 63EE 63DE absh data negh,3 227 63F0 0003 228 63F2 4142 text 'ABS ' 228 63F4 5320 229 63F6 63F8 abs_ data $+2 230 63F8 0754 abs *stack ; compute abs of the word on TOS 231 63FA 045C b *next 232 ;] 233 234 ;[ MIN n1 n2 -- n3 79 "min" 235 ; n3 is the lesser of n1 and n2 according to the operation of < . 236 63FC 63EE minh data absh,3 236 63FE 0003 237 6400 4D49 text 'MIN ' 237 6402 4E20 238 6404 6406 min data $+2 239 6406 8534 c *stack+,*stack ; compare n2 and n1 (and pop n2) 240 6408 1101 jlt keepn2 ; keep n2 if it's lower 241 640A 045C b *next ; otherwise keep n1 242 640C C524 keepn2 mov @-2(stack),*stack ; keep n2 242 640E FFFE 243 6410 045C b *next 244 ;] 245 246 ;[ MAX n1 n2 -- n3 79 "max" 247 ; n3 is the greater of n1 and n2 according to the operation of > . 248 6412 63FC maxh data minh,3 248 6414 0003 249 6416 4D41 text 'MAX ' 249 6418 5820 250 641A 641C max data $+2 251 641C 8534 c *stack+,*stack ; compare n2 and n1 (and pop n2) 252 641E 15F6 jgt keepn2 ; keep n2 if it's higher 253 6420 045C b *next ; otherwise keep n1 254 ;] 255 256 257 ; Floored math subroutines: 258 259 ;[ Signed divide using Floored Integer Division 260 ; Divides a 32 bit value in r1 and r2 by a 16 bit value in r0 261 ; Inputs: 262 ; r0=divisor 263 ; r1=upper 16 bits dividend 264 ; r2=lower 16 bits dividend 265 ; Outputs: 266 ; r1=16-bit quotient 267 ; r2=16-bit remainder 268 sidiv ; set flags to reflect signs of operands, and force operands positive... 269 6422 04CE clr r14 ; sign of divisor (-1=negative sign) 270 6424 04CF clr r15 ; sign of dividend (-1=negative sign) 271 6426 0740 abs r0 ; force divisor positive 272 6428 1501 jgt sdiv1 ; if positive then jump 273 642A 070E seto r14 ; flag negative divisor 274 642C C041 sdiv1 mov r1,r1 ; check sign of dividend 275 642E 1304 jeq sdiv2 276 6430 1503 jgt sdiv2 ; if positive then jump 277 6432 0541 inv r1 ; otherwise negate the dividend 278 6434 0502 neg r2 ; 279 6436 070F seto r15 ; and flag dividend as negative 280 ; perform division... 281 6438 C202 sdiv2 mov r2,r8 ; store a copy of the dividend 282 643A 3C40 div r0,r1 ; perform the division. r1=quot, r2=rem 283 ; check if floor should be applied... (signs different and remainder<>0) 284 643C 83CE sdiv3 c r14,r15 ; compare signs of dividend and divisor 285 643E 1309 jeq signdo ; if same then jump 286 6440 0501 neg r1 ; negate quotient 287 6442 C082 mov r2,r2 ; check remainder 288 6444 1306 jeq signdo ; jump if no remainder 289 ; apply floor rule... 290 6446 0601 floor dec r1 ; floor the quotient 291 ; compute remainder remainder=(divisor*quotient)-dividend 292 6448 C241 mov r1,r9 ; get floored quotient 293 644A 0749 abs r9 ; force positive 294 644C 3A40 mpy r0,r9 ; divisor*quotient (result in r10) 295 644E 6288 s r8,r10 ; subtract dividend 296 6450 C08A mov r10,r2 ; overwrite original remainder 297 ; apply sign of divisor to remainder 298 6452 C38E signdo mov r14,r14 ; check sign of divisor 299 6454 1101 jlt floor1 ; if negative then jump 300 6456 045B rt ; otherwise we're done 301 6458 0502 floor1 neg r2 ; remainder takes sign of divisor 302 645A 045B rt ; done 303 ;] 304 305 ;[ Signed Multiply 306 ; multiplies two signed 16-bit values, n1 & n2, giving a signed 32-bit product 307 ; Inputs: 308 ; r0=n1 309 ; r1=n2 310 ; Outputs: 311 ; r1=product, upper 16-bits 312 ; r2=product, lower 16-bits 313 ; check if signs of inputs are different 314 645C C180 simul mov r0,r6 ; copy n1 315 645E 2981 xor r1,r6 ; check signs (r6=negative if signs differ) 316 6460 0740 abs r0 ; force positive 317 6462 0741 abs r1 ; force positive 318 6464 3840 mpy r0,r1 ; n1*n2 (product in r1 & r2) 319 ; if input signs were different then negate results 320 6466 C186 mov r6,r6 ; check signs flag 321 6468 1504 jgt simul1 ; if same then leave positive 322 646A 0541 inv r1 ; invert high word 323 646C 0502 neg r2 ; negate low word 324 646E 1701 jnc simul1 ; skip if no carry 325 6470 0581 inc r1 ; add 1 to high word to compensate for carry 326 6472 045B simul1 rt 327 ;] * * COPY 'C:\TI\Source\TurboForth\Bank0\0-04-Comparison.a99' * 1 ; _____ _ 2 ; / ____| (_) 3 ; | | ___ _ __ ___ _ __ __ _ _ __ _ ___ ___ _ __ 4 ; | | / _ \| '_ ` _ \| '_ \ / _` | '__| / __|/ _ \| '_ \ 5 ; | |____| (_) | | | | | | |_) | (_| | | | \__ \ (_) | | | | 6 ; \_____|\___/|_| |_| |_| .__/ \__,_|_| |_|___/\___/|_| |_| 7 ; | | 8 ; |_| 9 ; __ __ _ 10 ; \ \ / / | | 11 ; \ \ /\ / /___ _ __ __| |___ 12 ; \ \/ \/ // _ \| '__/ _` / __| 13 ; \ /\ /| (_) | | | (_| \__ \ 14 ; \/ \/ \___/|_| \__,_|___/ 15 16 ;[ = n1 n2 -- flag 83 "equals" 17 ; flag is true if n1 is equal to n2. 18 6474 6412 eqh data maxh,1 18 6476 0001 19 6478 3D20 text '= ' 20 647A 647C eq data $+2 21 647C 8534 c *stack+,*stack ; compare and pop n2 22 647E 1369 jeq sTrue ; set true if n1=n2 23 6480 106A jmp sFalse ; else set result to false 24 ;] 25 26 ;[ > n1 n2 -- flag 83 "greater-than" 27 ; flag is true if n1 is greater than n2. 28 ; -32768 32767 > must return false. 29 ; -32768 0 > must return false. 30 6482 6474 gth data eqh,1 30 6484 0001 31 6486 3E20 text '> ' 32 6488 648A gt data $+2 33 648A 8534 c *stack+,*stack ; compare n2 to n1. pop n2 34 648C 1162 jlt sTrue ; set true if n2 35 648E 1063 jmp sFalse ; else set result to false 36 ;] 37 38 ;[ < n1 n2 -- flag 83 "less-than" 39 ; flag is true if n1 is less than n2. 40 ; -32678 32767 < must return true. 41 ; -32768 0 < must return true. 42 6490 6482 lth data gth,1 42 6492 0001 43 6494 3C20 text '< ' 44 6496 6498 lt data $+2 45 6498 8534 c *stack+,*stack ; compare n2 to n1. pop n2 46 649A 155B jgt sTrue ; set true if n2>n1 47 649C 105C jmp sFalse ; else set result to false 48 ;] 49 50 ;[ >= n1 n2 -- flag 51 ; returns true if n1>=n2 52 649E 6490 gteh data lth,2 52 64A0 0002 53 64A2 3E3D text '>=' 54 64A4 64A6 gte data $+2 55 64A6 8534 c *stack+,*stack ; compare n2 to n2. pop n2 56 64A8 1154 jlt sTrue ; set true if n2 Assembly Complete - Errors: 0, Warnings: 0 ------ Symbol Listing ------ __DUP ABS:7F06 __dup _ADD ABS:83A2 _add _ALIGN ABS:6CFE _align _ALLOT ABS:6D2C _allot _BIT0 ABS:78B4 _bit0 _BIT1 ABS:78B6 _bit1 _BLKQ ABS:689E _blkq _BLOCK ABS:671E _block _BUF ABS:68B2 _buf _CA1 ABS:7B4A _ca1 _CART ABS:7B6A _cart _CBOOT ABS:7E9C _cboot _CFA ABS:6BF4 _cfa _CLALL ABS:7B46 _clall _CLEAN ABS:6870 _clean _CLS ABS:6132 _cls _CMOVE ABS:65C0 _cmove _CMOVF ABS:65D0 _cmovf _COLOR ABS:63DE _color _COMAB ABS:6CEE _comab _COMMA ABS:6CD0 _comma _COMPI ABS:6D36 _compil _COPYW ABS:65EE _copyw _COUNT ABS:6D60 _count _DATA ABS:66D6 _data _DCHAR ABS:6298 _dchar _DEPTH ABS:78E8 _depth _DIRTY ABS:687C _dirty _DNOUT ABS:6566 _dnout _DOWN ABS:6512 _down _DOWN0 ABS:652A _down0 _DOWN1 ABS:654A _down1 _DOWN2 ABS:655C _down2 _DROP ABS:838A _drop _DUP ABS:8382 _dup _DUP2 ABS:6B0A _dup2 _EDIT ABS:6EA2 _edit _EDIT1 ABS:6EB6 _edit1 _EDIT2 ABS:6EBE _edit2 _EDIT3 ABS:6EC2 _edit3 _FCFND ABS:7A30 _fcfnd _FCLOP ABS:7A1E _fclop _FCLOS ABS:7A10 _fclos _FCXIT ABS:7A2E _fcxit _FEOF ABS:7AFC _feof _FGERR ABS:7A60 _fgerr _FGET ABS:7A34 _fget _FGXIT ABS:7A5E _fgxit _FICLL ABS:7904 _ficll _FILE ABS:78FA _file _FILL ABS:65AE _fill _FLUSH ABS:67AE _flush _FOERR ABS:7A06 _foerr _FOPEN ABS:79AA _fopen _FP1 ABS:7AA0 _fp1 _FP2 ABS:7AB4 _fp2 _FPERR ABS:7AC2 _fperr _FPUT ABS:7A70 _fput _FPVDP ABS:7AC8 _fpvdp _FPXIT ABS:7AC0 _fpxit _FREC ABS:7AE2 _frec _GCHAR ABS:6280 _gchar _GMODE ABS:6192 _gmode _HCHAR ABS:6250 _hchar _HEADR ABS:6C92 _headr _HIDE ABS:6D0E _hide _IMM ABS:6D1C _imm _JOYST ABS:615A _joyst _LEFT ABS:643A _left _LEFT1 ABS:645C _left1 _LIT ABS:8368 _lit _LWRAP ABS:6456 _lwrap _MAGFY ABS:62E4 _magfy _MKBLK ABS:68F0 _mkblk _MTBUF ABS:6854 _mtbuf _MUL ABS:83AA _mul _NEXT ABS:8326 _next _NTS ABS:6DEC _nts _NUMBR ABS:6BBA _numbr _OVER ABS:838E _over _PANEL ABS:656C _panel _PICK ABS:78B8 _pick _PLUS1 ABS:8396 _plus1 _PLUS2 ABS:839A _plus2 _QDIRT ABS:6888 _qdirt _RIGHT ABS:6478 _right _RIGHT ABS:649E _right1 _RND ABS:6D42 _rnd _ROLL ABS:78C6 _roll _RWRAP ABS:6498 _rwrap _SAMS ABS:65FE _sams _SAY ABS:664E _say _SCREN ABS:63F8 _scren _SCROL ABS:640A _scrol _SETBK ABS:68E0 _setbk _SMLST ABS:638E _smlst _SPACE ABS:6C90 _space _SPAN ABS:A04C _span _SPCOL ABS:630E _spcol _SPGET ABS:6352 _spget _SPKNG ABS:662C _spkng _SPLOC ABS:632C _sploc _SPMOV ABS:63A4 _spmov _SPPAT ABS:6370 _sppat _SPRIT ABS:62B4 _sprit _STATE ABS:A048 _state _STR ABS:6DD2 _str _STREM ABS:6668 _strem _STRI1 ABS:6DA8 _stri1 _STRI2 ABS:6DBE _stri2 _STRIN ABS:6D8C _strin _SUB ABS:83A6 _sub _SUB2 ABS:839E _sub2 _SWAP ABS:835C _swap _TRAIL ABS:6D6E _trail _TRCOM ABS:6B9A _trcom _UP ABS:64BE _up _UP0 ABS:64CE _up0 _UP1 ABS:64D0 _up1 _UP2 ABS:64F0 _up2 _UP3 ABS:6500 _up3 _UPDAT ABS:6840 _updat _UPOUT ABS:650A _upout _USE ABS:66EA _use _USE3 ABS:66F8 _use3 _VCHAR ABS:625C _vchar _VMBR ABS:7806 _vmbr _VMBR1 ABS:7814 _vmbr1 _VMBR2 ABS:77FE _vmbr2 _VMBRI ABS:77F8 _vmbri _VMBW ABS:7846 _vmbw _VMBW0 ABS:7854 _vmbw0 _VMBW1 ABS:7864 _vmbw1 _VMBW2 ABS:784C _vmbw2 _VMBWX ABS:7870 _vmbwx _VSBM1 ABS:7890 _vsbm1 _VSBR ABS:77E4 _vsbr _VSBW ABS:781E _vsbw _VSBW0 ABS:782C _vsbw0 _VSBWM ABS:7872 _vsbwm _VSBWM ABS:7878 _vsbwm2 _VWTR ABS:789E _vwtr _WARN ABS:A066 _warn _WORD ABS:6B1A _word _WWRAP ABS:A00A _wwrap _ZBRNC ABS:83B4 _zbrnch AB0RT ABS:7464 ab0rt AB0RTH ABS:745A ab0rth ABORT ABS:7432 abort ABORT_ ABS:7452 abort_ ABORTH ABS:7428 aborth ABS_ ABS:63F6 abs_ ABSH ABS:63EE absh ABTTXT ABS:742C abttxt ADD ABS:631E add ADDH ABS:6318 addh ADDTOH ABS:705E addtoh ADDTOX ABS:7076 addtox ADRLST ABS:7CBA adrlst AFTERI ABS:607A afteri AGAIN ABS:66A0 again AGAINH ABS:6696 againh AHEAD ABS:6564 ahead ALIGN ABS:70EC align ALIGNH ABS:70E2 alignh ALLFIN ABS:71EE allfin ALLOT ABS:70A2 allot ALLOTH ABS:7098 alloth ALTCFA ABS:6FAA altcfa AND ABS:67D2 and ANDH ABS:67CA andh ASCII ABS:78D8 ascii ASCII1 ABS:770B ascii1 ASCII2 ABS:7713 ascii2 ASCII3 ABS:771B ascii3 ASCII4 ABS:7723 ascii4 ASCII5 ABS:772B ascii5 ASCII6 ABS:7733 ascii6 ASCII7 ABS:773B ascii7 ASCIIH ABS:78CE asciih ASCIIX ABS:78E6 asciix AUTORL ABS:A084 autorl AUTORP ABS:A082 autorp BACK1 ABS:6A20 back1 BACK2 ABS:6A24 back2 BADBK1 ABS:73B6 badbk1 BADBLK ABS:73AA badblk BALTXT ABS:7596 baltxt BANK0 ABS:606A bank0 BANK1 ABS:8332 bank1 BANK1_ ABS:606C bank1_ BASE ABS:A05C base BASE_ ABS:76FC base_ BASEH ABS:76F4 baseh BCLEAN ABS:7CC4 bclean BEGCNT ABS:A086 begcnt BEGERR ABS:71DC begerr BEGIN ABS:6670 begin BEGINH ABS:6666 beginh BEGTXT ABS:7581 begtxt BFREE ABS:699E bfree BIT1 ABS:695E bit1 BITMSK ABS:7996 bitmsk BL_ ABS:6AC8 bl_ BLCTXT ABS:75B9 blctxt BLH ABS:6AC2 blh BLK ABS:7B4E blk BLK0 ABS:A1B6 blk0 BLK1 ABS:A1BA blk1 BLK2 ABS:A1BE blk2 BLK3 ABS:A1C2 blk3 BLK4 ABS:A1C6 blk4 BLK5 ABS:A1CA blk5 BLKERR ABS:679A blkerr BLKFB ABS:6740 blkfb BLKH ABS:7B46 blkh BLKMSG ABS:75CB blkmsg BLKNIM ABS:6738 blknim BLKNUM ABS:A1B2 blknum BLKNXT ABS:676C blknxt BLKQ ABS:7CF8 blkq BLKQH ABS:7CF0 blkqh BLKTXT ABS:76F4 blktxt BLKVDP ABS:7D3E blkvdp BLKVEC ABS:A002 blkvec BLNKLN ABS:6EF6 blnkln BLOAD1 ABS:7DF0 bload1 BLOAD2 ABS:7E2E bload2 BLOADH ABS:7DE4 bloadh BLOCK ABS:7B98 block BLOCK2 ABS:7BA4 block2 BLOCKH ABS:7B8E blockh BLOCKS ABS:0006 blocks BNFB ABS:6790 bnfb BOOTFN ABS:7D4A bootfn BOOTLP ABS:7BF0 bootlp BOOTUP ABS:60D6 bootup BRANCH ABS:65E4 branch BREAK ABS:6C54 break BREAK1 ABS:6C6E break1 BREAKH ABS:6C4A breakh BRKMSG ABS:6C70 brkmsg BRNCHH ABS:65DA brnchh BSAVE ABS:7D7E bsave BSAVE1 ABS:7D88 bsave1 BSAVE2 ABS:7DC2 bsave2 BSAVEH ABS:7D74 bsaveh BUF ABS:7D08 buf BUFADD ABS:1C20 bufadd BUFH ABS:7D00 bufh BUFRPT ABS:68BC bufrpt BUFXIT ABS:68DC bufxit BUMPY ABS:6A2A bumpY BYE ABS:6F2E bye BYEH ABS:6F26 byeh CALCSR ABS:7398 calcsr CASCHK ABS:6B4E caschk CASCNT ABS:A082 cascnt CASE ABS:6600 case CASEH ABS:65F8 caseh CASERR ABS:71B8 caserr CASOUT ABS:6B6A casout CASSEN ABS:A056 cassen CASTXT ABS:756D castxt CBA ABS:6978 cba CBOOT ABS:6106 cboot CBOOT1 ABS:7EA8 cboot1 CBOOTX ABS:7EB4 cbootx CCLOP ABS:7C12 cclop CCLOP1 ABS:7C1A cclop1 CCOMMA ABS:70DA ccomma CCOMMH ABS:70D4 ccommh CCP ABS:6F14 ccp CELLP ABS:62DA cellp CELLPH ABS:62D0 cellph CELLS ABS:6306 cells CELLSH ABS:62FC cellsh CFA ABS:6BF2 cfa CFAH ABS:6BEA cfah CFLASH ABS:6E22 cflash CHAR ABS:78C4 char CHARH ABS:78BC charh CHARP ABS:62E6 charp CHARPH ABS:62DC charph CHARS ABS:68A4 chars CHARSH ABS:689A charsh CHK80 ABS:72A0 chk80 CHKENT ABS:6F4E chkent CHKNUM ABS:734C chknum CHRFH ABS:6868 chrfh CHRFTC ABS:686E chrftc CLC ABS:60AC clc CLEAN ABS:7366 clean CLEAN1 ABS:738C clean1 CLEANH ABS:7CBA cleanh CLIPX ABS:6DBC clipx CLIPX2 ABS:7200 clipx2 CLIPXG ABS:71C0 clipxg CLIPXH ABS:71BC clipxh CLIPXL ABS:71F0 clipxl CLIPYG ABS:7220 clipyg CLIPYH ABS:724C clipyh CLIPYL ABS:7226 clipyl CLOAD ABS:7C68 cload CLOAD1 ABS:7C78 cload1 CLOADH ABS:7C5E cloadh CLOSE ABS:0001 close CLRLOP ABS:7BBC clrlop CLS ABS:6D76 cls CLS_ ABS:613A cls_ CLSALL ABS:7496 clsall CLSH ABS:6D6E clsh CMOVE ABS:6982 cmove CMOVEH ABS:6978 cmoveh CMOVF ABS:6994 cmovf CMOVFH ABS:698A cmovfh CMOVLP ABS:65C8 cmovlp CMVEXT ABS:65EA cmvext CMVFLP ABS:65E0 cmvflp CNRDAT ABS:74CC cnrdat CNXTCH ABS:6B06 cnxtch CODEH ABS:7148 codeh CODING ABS:A068 coding COL32D ABS:6234 col32d COL40D ABS:622A col40d COL80D ABS:623E col80d COLD ABS:6166 cold COLDH ABS:615C coldh COLNAM ABS:74CE colnam COLNM1 ABS:74E4 colnm1 COLON ABS:7116 colon COLONH ABS:7110 colonh COLOR ABS:7A4C color COLORH ABS:7A42 colorh COMBRA ABS:60A4 combra COMMA ABS:70CC comma COMMAH ABS:70C6 commah COMMAX ABS:6CEA commax COMPIH ABS:7256 compih COMPIL ABS:7262 compile COMXIT ABS:6BB8 comxit CONST ABS:6FFC const CONSTH ABS:6FF0 consth CONT ABS:691A cont COPYW ABS:69C0 copyw COPYWH ABS:69B6 copywh COPYWL ABS:65F6 copywl CORNER ABS:74AA corner COUNT ABS:78F2 count COUNTH ABS:78E8 counth CPL ABS:7668 cpl CPLH ABS:7660 cplh CPYPNT ABS:7ED2 cpypnt CR ABS:6E92 cr CREATE ABS:6F9A create CREATH ABS:6F90 creath CREXIT ABS:6EA8 crexit CRH ABS:6E8C crh CRNLP ABS:74AE crnlp CRTIME ABS:6FA4 crtime CRTLP ABS:6CB8 crtlp CSING ABS:73A4 csing CSR1 ABS:7392 csr1 CSRDEF ABS:75F2 csrdef CSRFLG ABS:A080 csrflg CSROFF ABS:737A csroff CSRON ABS:7374 csron CSRWRT ABS:6E4E csrwrt CSRX ABS:A07C csrx CSRY ABS:A07E csry CSTART ABS:60D4 cstart CURSRD ABS:A024 cursrd CVA ABS:7BB4 cva DATA1 ABS:7ADE data1 DATA2 ABS:7AEA data2 DATA8 ABS:6AE8 data8 DATAH ABS:7AC0 datah DATCR ABS:6A64 datCR DCHAR ABS:79A6 dchar DCHARH ABS:799C dcharh DECH ABS:77D0 dech DECI ABS:77DC deci DECMAL ABS:6AEA decmal DELAY ABS:75EA delay DELKEY ABS:0003 delkey DEPTH ABS:6240 depth DEPTHH ABS:6236 depthh DFA ABS:6C1E dfa DFA1 ABS:6C24 dfa1 DFAFND ABS:6C46 dfafnd DFAH ABS:6C14 dfah DIRTIH ABS:7CDE dirtih DIRTY ABS:7CD6 dirty DIRTYH ABS:7CCC dirtyh DIRTYQ ABS:7CE8 dirtyq DISBLK ABS:763A disblk DISKIO ABS:69B8 diskio DISLOP ABS:764E dislop DISUPD ABS:762C disupd DIV2 ABS:630E div2 DIV2H ABS:6308 div2h DIVS ABS:7674 divs DLENTR ABS:69E2 dlentr DLY42 ABS:611A dly42 DLYLOP ABS:75EC dlylop DO ABS:66F6 do DO1 ABS:66DA do1 DO1H ABS:66D4 do1h DOBOOT ABS:A04E doboot DOCFL ABS:6F32 docfl DOCMD1 ABS:7B24 docmd1 DOCNT ABS:A07E docnt DOCOL ABS:8320 docol DOCON ABS:7008 docon DODCMD ABS:7B1A dodcmd DODIG ABS:6E56 dodig DODIV ABS:6E24 dodiv DODOES ABS:6FB6 dodoes DOERR ABS:71A6 doerr DOERTX ABS:755F doertx DOES ABS:6FE6 does DOESH ABS:6FDC doesh DOH ABS:66EE doh DOINS ABS:72EA doins DOINS1 ABS:7312 doins1 DOINSX ABS:733E doinsx DOINV ABS:7C6C doinv DOMARK ABS:6F84 domark DOPTO ABS:7084 dopto DOSIGN ABS:A064 dosign DOT ABS:783C dot DOT1 ABS:7840 dot1 DOTH ABS:7836 doth DOTO ABS:7056 doto DOTOH ABS:704E dotoh DOTR ABS:7860 dotr DOTRH ABS:785A dotrh DOTS ABS:624E dots DOTS1 ABS:6260 dots1 DOTS3 ABS:6274 dots3 DOTS4 ABS:6276 dots4 DOTSIN ABS:A05A dotsin DOTST ABS:627C dotst DOTTXT ABS:6284 dottxt DOVAR ABS:7756 dovar DOVDP2 ABS:621C dovdp2 DOWWRA ABS:6CB6 dowwrap DPL ABS:A054 dpl DRAWD ABS:73B6 drawd DRAWS ABS:7408 draws DROP ABS:6172 drop DROP2 ABS:75E0 drop2 DROP2H ABS:75D6 drop2h DROPH ABS:616A droph DSRDT8 ABS:6ACE dsrdt8 DSRDTA ABS:6AD2 dsrdta DSRLNK ABS:69DE dsrlnk DSRLWS ABS:A156 dsrlws DSRVEC ABS:A00C dsrvec DSTACK ABS:A2C6 dstack DSTYPE ABS:A160 dstype DUP ABS:6186 dup DUP0H ABS:61F4 dup0h DUP2 ABS:75EE dup2 DUP2H ABS:75E6 dup2h DUPH ABS:617E duph ECODE ABS:7170 ecode ECODEH ABS:7166 ecodeh EDBLK ABS:A086 edblk EDF4 ABS:7162 edF4 EDIT ABS:7F18 edit EDIT_ ABS:7F30 edit_ EDIT0 ABS:7F3A edit0 EDIT1 ABS:7F54 edit1 EDIT3 ABS:7F58 edit3 EDITH ABS:7F10 edith EDML2 ABS:6EFE edml2 EDML3 ABS:6F12 edml3 EDML4 ABS:6F02 edml4 EDML5 ABS:6F16 edml5 EDML6 ABS:6F22 edml6 EDML7 ABS:6F2C edml7 EDNEXT ABS:7402 ednext ELSE ABS:65CC else ELSEH ABS:65C4 elseh EMIT ABS:6D98 emit EMIT_ ABS:6DA0 emit_ EMITH ABS:6D90 emith ENDB0 ABS:7FF0 endB0 ENDB1 ABS:7F4A endB1 ENDCAH ABS:6640 endcah ENDCAS ABS:664C endcas ENDOF ABS:6634 endof ENDOFH ABS:662A endofh EPAGE ABS:A07A epage EQ ABS:647A eq EQH ABS:6474 eqh EQZ ABS:64D2 eqz EQZH ABS:64CC eqzh ERRNUM ABS:A038 errnum ERROR ABS:752C error ERRTXT ABS:7590 errtxt ERRXIT ABS:7500 errxit EVAL ABS:6B96 eval EVALH ABS:6B8A evalh EXECUT ABS:72AA execut EXEH ABS:729E exeh EXIT ABS:832C exit EXITH ABS:610E exith EXITT ABS:6116 exitt EXP1 ABS:6A52 exp1 EXP2 ABS:6A5A exp2 EXPCNT ABS:A060 expcnt EXPCTH ABS:69C8 expcth EXPECT ABS:69D2 expect EXPNXT ABS:69E2 expnxt EXROLL ABS:78E6 exroll F1BUF ABS:1828 f1buf F1EOL ABS:70F2 f1eol F1PAB ABS:1800 f1pab F2BUF ABS:1950 f2buf F2PAB ABS:1928 f2pab F3BUF ABS:1A78 f3buf F3PAB ABS:1A50 f3pab F7EXIT ABS:715A f7exit FAC ABS:834A fac FADDPH ABS:6838 faddph FALLOC ABS:A1AA falloc FALSE ABS:7800 false FALSEH ABS:77F6 falseh FBLOCK ABS:7C52 fblock FBUF ABS:7E5C fbuf FBUFH ABS:7E52 fbufh FCLOSE ABS:7E84 fclose FCLOSH ABS:7E7A fclosh FDOCHR ABS:792E fdochr FDODIG ABS:7954 fdodig FDONE ABS:7982 fdone FEOF ABS:7EC6 feof FEOFH ABS:7EBC feofh FETCH ABS:6830 fetch FETCHH ABS:682A fetchh FEXIT ABS:7A68 fexit FFAHH ABS:7746 ffahh FFAIH ABS:7750 ffaih FFAIHM ABS:A01C ffaihm FFAILM ABS:A01A ffailm FFALH ABS:775C ffalh FFAML ABS:7766 ffaml FFOPT ABS:7968 ffopt FGET ABS:7E94 fget FGETH ABS:7E8C fgeth FILE1 ABS:7E4A file1 FILEH ABS:7E42 fileh FILL ABS:6970 fill FILLH ABS:6968 fillh FILLLP ABS:65B8 filllp FIND ABS:6AD8 find FIND1 ABS:6AF8 find1 FIND2 ABS:6B14 find2 FINDER ABS:72D0 finderr FINDH ABS:6AD0 findh FLERR ABS:6832 flerr FLEXIT ABS:6828 flexit FLGPTR ABS:A154 flgptr FLNEXT ABS:67C2 flnext FLNREC ABS:67F4 flnrec FLOOR ABS:6446 floor FLOOR1 ABS:6458 floor1 FLUSH ABS:7C98 flush FLUSH1 ABS:67B4 flush1 FLUSH2 ABS:6814 flush2 FLUSHH ABS:7C8E flushh FLUSHX ABS:67B2 flushx FNDBLK ABS:69B6 fndblk FNDBUF ABS:68D4 fndbuf FNDNXT ABS:6AEC fndnxt FNDVEC ABS:A006 fndvec FNEXT1 ABS:658C fnext1 FNXTOP ABS:7948 fnxtop FOEND ABS:79C6 foend FOMASK ABS:798C fomask FOOPTS ABS:79A0 foopts FOPEN1 ABS:7E72 fopen1 FOPENH ABS:7E68 fopenh FOR ABS:6576 for FORCNT ABS:A080 forcnt FORG1 ABS:7408 forg1 FORGET ABS:73EE forget FORGTH ABS:73E4 forgth FORH ABS:656E forh FPUT ABS:7EA4 fput FPUTH ABS:7E9C fputh FREBUF ABS:6988 frebuf FREC ABS:7EB4 frec FRECH ABS:7EAC frech FREEH ABS:699C freeh FRMDSR ABS:6ABE frmdsr FTCHPP ABS:6840 ftchpp FVMBR ABS:6902 fvmbr FVMBW ABS:6912 fvmbw FWDREW ABS:0004 fwdrew GABORT ABS:65A6 gabort GCHAR ABS:7994 gchar GCHARH ABS:798A gcharh GENKEY ABS:7254 genkey GET2 ABS:659A get2 GET4 ABS:6592 get4 GETI ABS:679A geti GETIH ABS:6794 getih GETJ ABS:67AC getj GETJH ABS:67A6 getjh GETSTK ABS:166C getstk GETWOR ABS:72BA getword GEXIT ABS:6258 gexit GEXIT1 ABS:63F4 gexit1 GEXIT2 ABS:650E gexit2 GHERE ABS:780E ghere GKEYCX ABS:72BA gkeycx GKNO ABS:7274 gkno GLINK1 ABS:7E5E glink1 GLNKWS ABS:2000 glnkws GMODE ABS:795E gmode GMODEH ABS:7954 gmodeh GMODEX ABS:6228 gmodex GOTOXY ABS:6C80 gotoxy GOXYH ABS:6C76 goxyh GPLLNK ABS:7E54 gpllnk GPLLOP ABS:7E66 gpllop GPLST ABS:837C gplst GPLVEC ABS:A00E gplvec GPLWS ABS:83E0 gplws GR4 ABS:83E8 gr4 GR6 ABS:83EC gr6 GRMRA ABS:9802 grmra GRMRD ABS:9800 grmrd GRMWA ABS:9C02 grmwa GRMWD ABS:9C00 grmwd GT ABS:6488 gt GTE ABS:64A4 gte GTEH ABS:649E gteh GTEZ ABS:6548 gtez GTEZH ABS:6540 gtezh GTH ABS:6482 gth GTZ ABS:64FE gtz GTZH ABS:64F8 gtzh GXMAX ABS:77A6 gxmax GXMLAD ABS:7E5A gxmlad H20 ABS:6AEC h20 HAA ABS:A176 haa HCHAR ABS:7970 hchar HCHARH ABS:7966 hcharh HDOTH ABS:787A hdoth HDR0 ABS:6C98 hdr0 HDR1 ABS:6CA6 hdr1 HEADER ABS:6F42 header HEADR ABS:6F4C headr HEADRH ABS:6F38 headrh HELP ABS:7743 help HERE ABS:A046 here HERE_ ABS:76EC here_ HEREH ABS:76E6 hereh HEX ABS:77C4 hex HEXDOT ABS:7880 hexdot HEXH ABS:77BC hexh HFREE ABS:6940 hfree HFREEH ABS:6936 hfreeh HHEREH ABS:7806 hhereh HIDEME ABS:721C hideme HIDH ABS:7212 hidh HIMEM ABS:A2C6 himem HLINE ABS:75A6 hline HTIBH ABS:7650 htibh ICOMP ABS:727A icomp ICOMPH ABS:726C icomph IERR ABS:7356 ierr IF ABS:659C if IFCNT ABS:A07C ifcnt IFERR ABS:7558 iferr IFH ABS:6596 ifh IGLZ ABS:6E5E iglz IMM ABS:7232 imm IMMED ABS:8000 immed IMMH ABS:7224 immh IN ABS:A042 in IN_ ABS:770C in_ INCYC ABS:72D2 incyc INH ABS:7704 inh INIT ABS:7B76 init INIT1 ABS:7BDC init1 INS1 ABS:7352 ins1 INSOVR ABS:7340 insovr INSTXT ABS:76FF instxt INTERP ABS:72FE interp INTGO ABS:730A intgo INTH ABS:72F0 inth INTLP ABS:730C intlp INTOUT ABS:73A6 intout INTVEC ABS:A000 intvec INTXT ABS:75AB intxt INV_ ABS:6800 inv_ INVH ABS:67F8 invh INVLOP ABS:7C78 invlop IOERR ABS:6ADE ioerr IOERR1 ABS:7796 ioerr1 IOERRH ABS:778C ioerrh IS80C ABS:767A is80c ISDBL ABS:A052 isdbl ISR ABS:83C4 ISR ISRDES ABS:607A isrdes ISRNXT ABS:6084 isrnxt ISROUT ABS:608C isrout ISRXIT ABS:8354 isrxit ISSERR ABS:7204 isserr ISSPCH ABS:6684 isspch JOYST ABS:6D88 joyst JOYSTH ABS:6D7E joysth KEEPN2 ABS:640C keepn2 KEY ABS:6DD6 key KEYBD ABS:75E8 keybd KEYCC ABS:FFFFFF83 keyCC KEYCCR ABS:704C keyccr KEYCD ABS:FFFFFF84 keyCD KEYCD1 ABS:6FBA keycd1 KEYCDR ABS:6FA0 keycdr KEYCI ABS:FFFFFF89 keyCI KEYCI1 ABS:7014 keyci1 KEYCI2 ABS:7038 keyci2 KEYCIR ABS:6FF6 keycir KEYCO ABS:FFFFFF8F keyCO KEYCOR ABS:6F74 keycor KEYCP ABS:FFFFFF90 keyCP KEYCPR ABS:6F8E keycpr KEYCV ABS:FFFFFF96 keyCV KEYCVR ABS:706E keyCVr KEYD ABS:718C keyd KEYD1 ABS:71A6 keyd1 KEYD2 ABS:71AE keyd2 KEYDEV ABS:A022 keydev KEYDX ABS:71D2 keydx KEYE ABS:720A keye KEYEN1 ABS:6F6E keyen1 KEYF1 ABS:0003 keyF1 KEYF1R ABS:709E keyf1r KEYF1S ABS:70CC keyf1s KEYF2 ABS:0004 keyF2 KEYF2R ABS:7180 keyf2r KEYF3 ABS:0007 keyF3 KEYF3R ABS:7110 keyf3r KEYF4 ABS:0002 keyF4 KEYF7 ABS:0001 keyF7 KEYF7R ABS:7142 keyf7r KEYF9 ABS:000F keyF9 KEYF9R ABS:7102 keyf9r KEYFD ABS:0009 keyFD KEYFE ABS:000B keyFE KEYFEQ ABS:0005 keyFeq KEYFQR ABS:715C keyfqr KEYFS ABS:0008 keyFS KEYFX ABS:000A keyFX KEYIN ABS:8375 keyin KEYQ ABS:6E62 keyq KEYQH ABS:6E5A keyqh KEYQSR ABS:6E6A keyqsr KEYRET ABS:000D keyRET KEYS ABS:71D4 keys KEYX ABS:7230 keyx KMODE ABS:771E kmode KMODH ABS:7714 kmodh KSCN ABS:6DE2 kscn KSCN1 ABS:6DE4 kscn1 KSCN2 ABS:6E08 kscn2 KSCNH ABS:6DCE kscnh L8000 ABS:6B36 l8000 LAGAIN ABS:674C lagain LASTWD ABS:7F10 lastwd LATES_ ABS:76DE lates_ LATESH ABS:76D4 latesh LATEST ABS:A044 latest LBASE ABS:A05E lbase LBRACE ABS:7E2E lbrace LBRACK ABS:70FA lbrack LBRAKH ABS:70F4 lbrakh LDGADD ABS:0060 ldgadd LDVDPL ABS:61BE ldvdpl LDVDPR ABS:61B6 ldvdpr LEAVE ABS:6788 leave LEAVEH ABS:677E leaveh LFREE ABS:695A lfree LFREEH ABS:6950 lfreeh LFT1 ABS:7546 lft1 LFTLIN ABS:752E lftlin LHL ABS:7448 lhl LHL1 ABS:745E lhl1 LINK ABS:0000 link LINNUM ABS:75C3 linnum LIST_ ABS:7BB4 list_ LIST1 ABS:7BC8 list1 LISTH ABS:7BAC listh LIT ABS:70B2 lit LIT0 ABS:6084 lit0 LIT1 ABS:608C lit1 LIT8 ABS:6094 lit8 LITERH ABS:70B4 literh LITH ABS:70AA lith LITM1 ABS:609C litm1 LITRAL ABS:70C0 litral LMATCH ABS:6AFE lmatch LNKERR ABS:6ADC lnkerr LNKSLN ABS:6A2A lnksln LNKSLP ABS:6A10 lnkslp LOAD ABS:7C18 load LOADH ABS:7C10 loadh LOADLP ABS:66B6 loadlp LOCSPH ABS:79F8 locsph LOCSPR ABS:7A04 locspr LOGO ABS:7E26 logo LOMADJ ABS:6CE6 lomadj LOOP ABS:673E loop LOOP1 ABS:6718 loop1 LOOP1H ABS:6710 loop1h LOOP2 ABS:6726 loop2 LOOPCH ABS:6742 loopchk LOOPH ABS:6734 looph LOOPX ABS:6744 loopx LOWCAS ABS:7D56 lowcas LSFT ABS:680C lsft LSFTH ABS:6806 lsfth LSTBLK ABS:A1B4 lstblk LSTXIT ABS:7BF8 lstxit LT ABS:6496 lt LTE ABS:64B4 lte LTEH ABS:64AE lteh LTEZ ABS:6536 ltez LTEZH ABS:652E ltezh LTH ABS:6490 lth LTZ ABS:64F0 ltz LTZH ABS:64EA ltzh LZI ABS:A062 lzi MAGFY ABS:79CC magfy MAGFYH ABS:79C0 magfyh MARK ABS:655A mark MARKR ABS:6F5E markr MARKRH ABS:6F54 markrh MAX ABS:641A max MAXH ABS:6412 maxh MEMPTR ABS:7E34 memptr MENU ABS:600C menu MENU40 ABS:6026 menu40 MIN ABS:6404 min MINH ABS:63FC minh MKBLK ABS:7D2C mkblk MKBLKC ABS:7D34 mkblkc MKBLKH ABS:7D22 mkblkh MKCLSE ABS:6964 mkclse MKDERR ABS:6970 mkderr MKDSKL ABS:691E mkdskl MOD ABS:63D6 mod MODH ABS:63CE modh MODMAX ABS:7372 modmax MODTXT ABS:76FA modtxt MPADJ ABS:6CDA mpadj MTBUF ABS:7CB2 mtbuf MTBUFH ABS:7CA0 mtbufh MTBUFL ABS:685C mtbufl MTEXT ABS:602B mtext MUL ABS:632E mul MUL2 ABS:62F6 mul2 MUL2H ABS:62F0 mul2h MUL3 ABS:62F8 mul3 MULH ABS:6328 mulh NAMONE ABS:6A9C namone NAMPTR ABS:8356 namptr NAMSTO ABS:A178 namsto NAMTWO ABS:6AA4 namtwo NBLK ABS:7B60 nblk NBLKH ABS:7B58 nblkh NBUF ABS:7624 nbuf NBUFH ABS:761C nbufh NCOS ABS:72CC ncos NCOS1 ABS:72E4 ncos1 NDIRT ABS:689A ndirt NDSH ABS:6248 ndsh NEEDUD ABS:7616 needud NEG_ ABS:63E8 neg_ NEG2 ABS:63EA neg2 NEGH ABS:63DE negh NEQ ABS:64C4 neq NEQHH ABS:64BE neqhh NEQZ ABS:64E2 neqz NEQZH ABS:64DA neqzh NEXIT ABS:6C7A nexit NEXT ABS:000C NEXT NEXT1K ABS:694C next1k NEXTH ABS:6584 nexth NFERR ABS:749E nferr NFTXT ABS:75A1 nftxt NIMM ABS:7344 nimm NINN ABS:6E46 ninn NIP ABS:61D2 nip NIPH ABS:61CA niph NOBOOT ABS:73C2 noboot NOBOOT ABS:753A nobootm NOCODE ABS:738C nocode NODBL ABS:737C nodbl NODSR ABS:6AD8 nodsr NOIMM ABS:6B44 noimm NOKEY ABS:FF00 nokey NOMATC ABS:6B48 nomatch NOOFF ABS:6A56 nooff NOPAST ABS:709C nopast NOROM ABS:6A50 norom NOSCR ABS:7638 noscr NOSCRH ABS:762C noscrh NOSCRL ABS:A026 noscrl NOTFND ABS:7424 notfnd NOTICK ABS:72E6 notick NOWORD ABS:6B74 noword NROT ABS:61AC nrot NROTH ABS:61A4 nroth NSPK ABS:664A nspk NTS ABS:789E nts NTS1 ABS:78A6 nts1 NTSH ABS:7896 ntsh NUM0 ABS:6BEA num0 NUM1 ABS:6C14 num1 NUM2 ABS:6C20 num2 NUM3 ABS:6C28 num3 NUM4 ABS:6BEE num4 NUM5 ABS:6BFA num5 NUMBER ABS:6B76 number NUMBR1 ABS:6B82 numbr1 NUMBRH ABS:6B6C numbrh NUMEND ABS:6C70 numend NUMGO ABS:6C54 numgo NUMISD ABS:6C50 numisd NUMISL ABS:6C4A numisl NUMLZ ABS:6C2C numlz NUMVEC ABS:A004 numvec NXTDAT ABS:7C9E nxtdat NXTDIG ABS:6E4C nxtdig NXTFB ABS:6990 nxtfb NXTREC ABS:6950 nxtrec NXTSLT ABS:79B2 nxtslt OF ABS:6612 of OFCNT ABS:A084 ofcnt OFERR ABS:71CA oferr OFH ABS:660C ofh OFTXT ABS:7579 oftxt OHSHIT ABS:6C44 ohshit OK ABS:7362 ok OKTXT ABS:6150 oktxt OKX ABS:7364 okx ONCSR ABS:6F48 oncsr OPEN ABS:0000 open OR_ ABS:67E0 or_ ORH ABS:67DA orh OVER ABS:61C8 over OVERH ABS:61C0 overh OVR ABS:7368 ovr OVRTXT ABS:7705 ovrtxt PABBUF ABS:A182 pabbuf PABCC ABS:A185 pabcc PABFIL ABS:A18A pabfil PABFLG ABS:A181 pabflg PABLOC ABS:1B78 pabloc PABLRL ABS:A184 pablrl PABNLN ABS:A189 pabnln PABOPC ABS:A180 pabopc PABREC ABS:A186 pabrec PABSCO ABS:A188 pabsco PAD ABS:7776 pad PADEND ABS:7F44 padend PADH ABS:776E padh PADVEC ABS:A010 padvec PADX ABS:7786 padx PAE ABS:6D68 PAE PANC ABS:A036 panc PANEL ABS:7A82 panel PANELH ABS:7A78 panelh PANR ABS:A034 panr PANXY ABS:A032 panxy PARSNM ABS:6BBE parsnm PATCH ABS:A06A patch PC ABS:0003 pc PCREAT ABS:A018 pcreate PDOCON ABS:A016 pdocon PICK ABS:6212 pick PICKH ABS:620A pickh PICKX ABS:78C2 pickx PITCH ABS:0023 pitch PLOOH1 ABS:6750 plooh1 PLOOP ABS:6778 ploop PLOOP1 ABS:675A ploop1 PLOOPH ABS:676C plooph PLUS1 ABS:62BA plus1 PLUS1H ABS:62B4 plus1h PLUS2 ABS:62CE plus2 PLUS2H ABS:62C8 plus2h PNEXT ABS:A014 pnext PRGTOP ABS:A2C6 prgtop PTOH ABS:707A ptoh PUSHER ABS:6C88 pusher PWR ABS:6E10 pwr PWROUT ABS:6E20 pwrout QDUP ABS:61FC qdup QDUPX ABS:6208 qdupx QUIT ABS:6124 quit QUITH ABS:611C quith QUITKY ABS:009D quitky QUITLP ABS:6126 quitlp R0 ABS:0000 R0 R1 ABS:0001 R1 R10 ABS:000A R10 R11 ABS:000B R11 R12 ABS:000C R12 R13 ABS:000D R13 R14 ABS:000E R14 R15 ABS:000F R15 R2 ABS:0002 R2 R3 ABS:0003 R3 R4 ABS:0004 R4 R5 ABS:0005 R5 R6 ABS:0006 R6 R7 ABS:0007 R7 R8 ABS:0008 R8 R9 ABS:0009 R9 RBRACK ABS:7108 rbrack RBRAKH ABS:7102 rbrakh RDFER1 ABS:74CC rdfer1 RDFERR ABS:74B6 rdferr RDFTXT ABS:7586 rdftxt READ ABS:0002 read READSP ABS:669C readsp RECBUF ABS:1BA0 recbuf RECLN0 ABS:7A5C recln0 RECRSH ABS:7286 recrsh RECURS ABS:7292 recurs REFDN ABS:67C2 refdn REFILL ABS:0008 refill REFUP ABS:67BA refup REM ABS:6A6C rem REMH ABS:6A66 remh REPEAT ABS:66CC repeat REPETH ABS:66C2 repeth REPXIT ABS:752A repxit RET4TH ABS:710C ret4th RETB0 ABS:833A retB0 RETBNK ABS:A06E retbnk RETSTK ABS:A28A retstk RL1 ABS:747A rl1 RLOOP ABS:7504 rloop RND ABS:781E rnd RNDH ABS:7816 rndh RNDX ABS:6D5C rndx ROLL ABS:622E roll ROLLH ABS:6226 rollh ROLLLP ABS:78DA rolllp ROMSPK ABS:60FA romspk ROMSPX ABS:612E romspx ROT ABS:6190 rot ROTH ABS:6188 roth ROWNUM ABS:746C rownum ROWTXT ABS:76E4 rowtxt RPF ABS:76BC rpf RPFH ABS:76B4 rpfh RRSTAC ABS:6154 rrstack RS0 ABS:A020 rs0 RSC ABS:629E rsc RSCH ABS:6298 rsch RSFT ABS:681E rsft RSFTH ABS:6818 rsfth RSPOP ABS:62AC rspop RSPOPH ABS:62A6 rspoph RSPSHH ABS:628A rspshh RSPUSH ABS:6290 rspush RSRC ABS:74DC rsrc RSRC_ ABS:74EC rsrc_ RSRC1 ABS:7500 rsrc1 RSTACK ABS:0005 rstack RSTSP ABS:6AEE rstsp RSTSP1 ABS:6AF6 rstsp1 RSTSP3 ABS:6B02 rstsp3 RT1 ABS:756E rt1 RT2 ABS:7578 rt2 RT4TH ABS:6F84 rt4th RTDATA ABS:7AF6 rtdata RTDATH ABS:7AEC rtdath RTLIN ABS:7550 rtlin RTNAD ABS:7E58 rtnad RU80C ABS:73E6 ru80c RUNISR ABS:834C runisr S0 ABS:A01E s0 S0_ ABS:77B4 s0_ S0H ABS:77AE s0h S32COL ABS:61AC s32col S40COL ABS:61A6 s40col S80COL ABS:61B2 s80col SAL ABS:A088 sal SAMS ABS:7BA6 sams SAMS_ ABS:692E sams_ SAMSH ABS:6926 samsh SAV8A ABS:A148 sav8a SAVCRU ABS:A14A savcru SAVENT ABS:A14C savent SAVKEY ABS:A028 savkey SAVLEN ABS:A14E savlen SAVPAB ABS:A150 savpab SAVVER ABS:A152 savver SAY ABS:7AA6 say SAYH ABS:7A9E sayh SAYXIT ABS:6664 sayxit SCLUP_ ABS:6EBE sclup_ SCNBLK ABS:69A0 scnblk SCNKEY ABS:75BE scnkey SCNKY1 ABS:75DE scnky1 SCNNXT ABS:69A8 scnnxt SCREEN ABS:7A5E screen SCRLNO ABS:6F0A scrlno SCRLUP ABS:6EAA scrlup SCRLUT ABS:6432 scrlut SCRNH ABS:7A54 scrnh SCROLH ABS:7A66 scrolh SCROLL ABS:7A70 scroll SCRX ABS:A028 scrX SCRY ABS:A02A scrY SDELIM ABS:A050 sdelim SDIV ABS:63C6 sdiv SDIV1 ABS:642C sdiv1 SDIV2 ABS:6438 sdiv2 SDIV3 ABS:643C sdiv3 SDIVH ABS:63C0 sdivh SEED ABS:A076 seed SEMI ABS:7186 semi SEMI2 ABS:71F4 semi2 SEMI3 ABS:7200 semi3 SEMIH ABS:7180 semih SENS ABS:7648 sens SENSH ABS:7640 sensh SETBLH ABS:7D10 setblh SETBLK ABS:7D1A setblk SETW ABS:786C setw SFALSE ABS:6556 sFalse SGET3 ABS:658A sget3 SGET4 ABS:6588 sget4 SGET5 ABS:6586 sget5 SGO ABS:6A7A sgo SGO2 ABS:6A80 sgo2 SIDIV ABS:6422 sidiv SIGN ABS:78AC sign SIGNDO ABS:6452 signdo SIMUL ABS:645C simul SIMUL1 ABS:6472 simul1 SKIPBS ABS:6A30 skipbs SKIPLD ABS:60FC skipld SKIPUD ABS:7638 skipud SMLIST ABS:A108 smlist SMLST ABS:7A28 smlst SMLSTH ABS:7A1E smlsth SMOD ABS:6362 smod SMOD1 ABS:6370 smod1 SMODH ABS:635A smodh SNDXIT ABS:7F0E sndxit SOUND ABS:7ED8 sound SOUNDH ABS:7ECE soundh SOURCE ABS:A058 source SPACE1 ABS:6D38 space1 SPACEH ABS:6D2E spaceh SPADDR ABS:66B2 spaddr SPADR ABS:A03C spadr SPAN ABS:7658 span SPAN1 ABS:765E span1 SPCES ABS:6D52 spces SPCES1 ABS:6D5C spces1 SPCESH ABS:6D48 spcesh SPCESX ABS:6D6C spcesx SPCHRD ABS:9000 spchrd SPCHWT ABS:9400 spchwt SPCHX ABS:669A spchx SPCNT ABS:A03A spcnt SPCSVC ABS:A03E spcsvc SPDATA ABS:834A spdata SPEECH ABS:607C speech SPF ABS:769A spf SPFH ABS:7692 spfh SPKNG ABS:7A96 spkng SPKNGH ABS:7A8A spkngh SPKROM ABS:662A spkROM SPPATH ABS:7A0C sppath SPRCLH ABS:79D4 sprclh SPRCOL ABS:79DE sprcol SPREAD ABS:6628 spread SPRITE ABS:79B8 sprite SPRITH ABS:79AE sprith SPRLCH ABS:79E6 sprlch SPRLOC ABS:79F0 sprloc SPRMOV ABS:7A3A sprmov SPRMV1 ABS:63BE sprmv1 SPRMVH ABS:7A30 sprmvh SPRPAT ABS:7A16 sprpat SPRTX ABS:62E0 sprtx SPS ABS:76A8 sps SPSH ABS:76A0 spsh SPSTAT ABS:8340 spstat SPSX ABS:76B0 spsx SPWORD ABS:72B2 spword SPYES ABS:6696 spyes SROM ABS:6A46 srom SSFLAG ABS:6629 ssflag SSLASH ABS:6330 sslash SSM ABS:6386 ssm SSMH ABS:637C ssmh STACK ABS:0004 stack STACKS ABS:A254 stacks STADD ABS:6860 stadd STADDH ABS:685A staddh START4 ABS:6052 start40 START8 ABS:605C start80 STARTB ABS:606E startB0 STARTB ABS:606E startB1 STATE_ ABS:76CC state_ STATE0 ABS:7338 state0 STATEH ABS:76C2 stateh STATUS ABS:0009 status STB ABS:6880 stb STBH ABS:687A stbh STKPNT ABS:8373 stkpnt STKTXT ABS:75AF stktxt STKUF ABS:73CC stkuf STKUFH ABS:73C4 stkufh STKX ABS:73E2 stkx STOR0H ABS:688C stor0h STOR0X ABS:6898 stor0x STORE ABS:6852 store STORE0 ABS:6892 store0 STOREH ABS:684C storeh STR ABS:791E str STRBUF ABS:A242 strbuf STRC1 ABS:6D9C strc1 STRCU ABS:60F4 strcu STRH ABS:7916 strh STRING ABS:7900 string STRM ABS:7AB8 strm STRMH ABS:7AAE strmh STRNB ABS:60DE strnb STRNG1 ABS:790E strng1 STRNGH ABS:78FA strngh STRSP2 ABS:60A6 strsp2 STRSP3 ABS:60C4 strsp3 STRSPK ABS:6090 strspk STRUE ABS:6552 sTrue STRXIT ABS:60F2 strxit SUB ABS:6326 sub SUB1 ABS:62C2 sub1 SUB1H ABS:62BC sub1h SUB2 ABS:62EE sub2 SUB2H ABS:62E8 sub2h SUBH ABS:6320 subh SUMODE ABS:A078 sumode SWAP ABS:617C swap SWAPH ABS:6174 swaph SWPB_ ABS:6220 swpb_ SWPBH ABS:621A swpbh SYNTH ABS:60FE synth SYNYES ABS:A040 synyes TBODYH ABS:6C08 tbodyh TEMP ABS:A070 temp TEMP2 ABS:A072 temp2 TEMP3 ABS:A074 temp3 TERM1 ABS:60BE term1 TESTLZ ABS:6E78 testlz TFNL ABS:7918 tfnl THEN ABS:65B4 then THENH ABS:65AC thenh THRU ABS:7B7A thru THRUH ABS:7B72 thruh THRULP ABS:7B84 thrulp TIB ABS:3420 tib TIB_ ABS:773E tib_ TIBADR ABS:A1CE tibadr TIBH ABS:7736 tibh TIBSIZ ABS:A04A tibsiz TICK ABS:7242 tick TICK2 ABS:7250 tick2 TICK2H ABS:724A tick2h TICKH ABS:723A tickh TLUT ABS:6E7E tlut TOBODY ABS:6C12 tobody TOH ABS:7034 toh TOHX ABS:704A tohx TOOBIG ABS:6916 toobig TOOSML ABS:6910 toosml TORAM ABS:7EB8 toRAM TOTBLK ABS:A1B0 totblk TOTERM ABS:60B6 toterm TOUTIL ABS:708C ToUtil TRAIL ABS:7934 trail TRAIL1 ABS:6D84 trail1 TRAIL2 ABS:6D7C trail2 TRAILH ABS:7926 trailh TRCOM ABS:6A7E trcom TRCOM1 ABS:6BB2 trcom1 TRCOMH ABS:6A78 trcomh TRLOUT ABS:6D82 trlout TRUE ABS:77F0 true TRUEH ABS:77E8 trueh TRUL1 ABS:73DC trul1 TSTRH ABS:793C tstrh TUCK ABS:61E0 tuck TUCKH ABS:61D8 tuckh TXT0 ABS:7684 txt0 TXT1 ABS:76A3 txt1 TXT2 ABS:76C2 txt2 TYPCMH ABS:6A86 typcmh TYPE ABS:6C94 type TYPE1 ABS:6C96 type1 TYPEH ABS:6C8C typeh TYPLP ABS:6CA4 typlp TYPOUT ABS:6CB4 typout TYPST1 ABS:7950 typst1 TYPSTR ABS:7942 typstr UDOT ABS:782C udot UDOTH ABS:7826 udoth UDOTR ABS:784E udotr UDOTRH ABS:7846 udotrh ULESS ABS:650C uless ULESSH ABS:6506 ulessh UMODH ABS:63A2 umodh UMSH ABS:6340 umsh UNBAL ABS:74AC unbal UNTIL ABS:6686 until UNTILH ABS:667C untilh UPDATE ABS:7C86 update UPDATH ABS:7C7C updath UPKEY ABS:72E8 upkey USE ABS:7B06 use USE1 ABS:7B0E use1 USEH ABS:7AFE useh USEXIT ABS:671A usexit USIGN ABS:78B4 usign USIGND ABS:7602 usignd USIGNH ABS:75F6 usignh USMOD ABS:63AC usmod USRISR ABS:A008 usrisr VALUE ABS:702E value VALUEH ABS:7024 valueh VAR ABS:701A var VARH ABS:700E varh VBLNK ABS:83D7 vblnk VCHAR ABS:7982 vchar VCHAR1 ABS:626E vchar1 VCHAR2 ABS:627A vchar2 VCHARH ABS:7978 vcharh VDPA ABS:8C02 vdpa VDPFH ABS:68A6 vdpfh VDPFTC ABS:68AC vdpftc VDPM ABS:6918 vdpm VDPR ABS:8800 vdpr VDPR1 ABS:A06C vdpr1 VDPRW ABS:68E8 vdprw VDPRWH ABS:68E0 vdprwh VDPSTR ABS:68C0 vdpstr VDPW ABS:8C00 vdpw VDPWH ABS:68BA vdpwh VDPWW ABS:7D58 vdpww VDPWWH ABS:68CE vdpwwh VDPX ABS:6924 vdpx VFIND ABS:6AE4 vfind VLINE ABS:7592 vline VLINE1 ABS:7598 vline1 VMBR ABS:7F82 vmbr VMBR1 ABS:7F92 vmbr1 VMBRH ABS:68FA vmbrh VMBW ABS:7FC2 vmbw VMBW0 ABS:7FD0 vmbw0 VMBW1 ABS:7FE4 vmbw1 VMBWH ABS:690A vmbwh VREAD ABS:6B90 vread VREAD1 ABS:6B92 vread1 VREAD2 ABS:6B96 vread2 VSBR ABS:7F60 vsbr VSBW ABS:7F9A vsbw VSBW0 ABS:7FA8 vsbw0 VSBWMI ABS:7880 vsbwmi WARN ABS:772E warn WARNH ABS:7726 warnh WFNLB ABS:7928 wfnlb WFTXT ABS:6D10 wftxt WHEAD ABS:7D3C whead WHERE ABS:7B20 where WHERE1 ABS:7B40 where1 WHEREH ABS:7B16 whereh WHILE ABS:66BA while WHILEH ABS:66B0 whileh WITHH ABS:6514 withh WITHIN ABS:651E within WKSPC ABS:8300 wkspc WORD ABS:6AA2 word WORD0 ABS:6AA8 word0 WORD1 ABS:6ABA word1 WORD2 ABS:6AB6 word2 WORDH ABS:6A9A wordh WORDS_ ABS:6CC2 words_ WORDS1 ABS:6CCA words1 WORDS2 ABS:6D02 words2 WORDS3 ABS:6CE8 words3 WORDS4 ABS:6CEA words4 WORDSH ABS:6CB8 wordsh WP ABS:A012 wp WRAP ABS:A030 wrap WRAP_ ABS:7678 wrap_ WRAPH ABS:7670 wraph WRD1 ABS:6B3E wrd1 WRD2 ABS:6B52 wrd2 WRDBUF ABS:A1D0 wrdbuf WRDFIN ABS:6B70 wrdfin WRDGB ABS:6B86 wrdgb WRDXIT ABS:6B7C wrdxit1 WRDXIT ABS:6B82 wrdxit2 WRITE ABS:0003 write WRKBUF ABS:A222 wrkbuf WSTR ABS:75B2 wstr WWRAP ABS:7614 wwrap WWRAPH ABS:760A wwraph XMAX ABS:A02C xmax XMAXH ABS:779E xmaxh XMLRTN ABS:7E90 xmlrtn XOR_ ABS:67EE xor_ XORH ABS:67E6 xorh XTAB27 ABS:200E xtab27 XTHRU ABS:7B8C xthru XUGLY ABS:6BE2 xugly XY ABS:6D1E xy XYA ABS:7580 xya XYH ABS:6D16 xyh YMAX ABS:A02E ymax ZBQ ABS:7F40 zbq ZBRCHH ABS:65EA zbrchh ZBRNCH ABS:65F6 zbrnch ZCHARS ABS:6A5E zchars ZEROCH ABS:7E4E zerochr ZEROS ABS:768A zeros ZEROSH ABS:7680 zerosh57 64AA 1353 jeq sTrue ; or if n2=n1 58 64AC 1054 jmp sFalse ; else set result to false 59 ;] 60 61 ;[ <= (SIGNED) ( n1 n2 -- flag ) 62 ; returns true if n1<=n2 63 64AE 649E lteh data gteh,2 63 64B0 0002 64 64B2 3C3D text '<=' 65 64B4 64B6 lte data $+2 66 64B6 8534 c *stack+,*stack ; compare n2 to n1. pop n2 67 64B8 154C jgt sTrue ; set true if n2>n1 68 64BA 134B jeq sTrue ; or if n2=n1 69 64BC 104C jmp sFalse ; else set result to false 70 ;] 71 72 ;[ <> ( n1 n2 -- flag ) 73 ; returns true if n1!=n2 74 64BE 64AE neqhh data lteh,2 74 64C0 0002 75 64C2 3C3E text '<>' 76 64C4 64C6 neq data $+2 77 64C6 8534 c *stack+,*stack ; compare n2 to n1. pop n2 78 64C8 1644 jne sTrue ; set true if n2<>n1 79 64CA 1045 jmp sFalse ; else set result to false 80 ;] 81 82 ;[ 0= w -- flag 83 "zero-equals" 83 ; flag is true if w is zero. 84 64CC 64BE eqzh data neqhh,2 84 64CE 0002 85 64D0 303D text '0=' 86 64D2 64D4 eqz data $+2 87 64D4 C514 mov *stack,*stack ; compare to tos to 0 88 64D6 133D jeq sTrue ; set true if tos=0 89 64D8 103E jmp sFalse ; else set result to false 90 ;] 91 92 ;[ 0<> ( x -- flag ) 93 ; returns true if x!=0 94 64DA 64CC neqzh data eqzh,3 94 64DC 0003 95 64DE 303C text '0<> ' 95 64E0 3E20 96 64E2 64E4 neqz data $+2 97 64E4 C514 mov *stack,*stack ; compare tos to 0 98 64E6 1635 jne sTrue ; set true if tos<>0 99 64E8 1036 jmp sFalse ; else set result to false 100 ;] 101 102 ;[ 0< n -- flag 83 "zero-less" 103 ; flag is true if n is less than zero (negative). 104 64EA 64DA ltzh data neqzh,2 104 64EC 0002 105 64EE 303C text '0<' 106 64F0 64F2 ltz data $+2 107 64F2 C514 mov *stack,*stack ; compare tos to 0 108 64F4 112E jlt sTrue ; set true if tos<0 109 64F6 102F jmp sFalse ; else set result to false 110 ;] 111 112 ;[ 0> n -- flag 83 "zero-greater" 113 ; flag is true if n is greater than zero. 114 64F8 64EA gtzh data ltzh,2 114 64FA 0002 115 64FC 303E text '0>' 116 64FE 6500 gtz data $+2 117 6500 C514 mov *stack,*stack ; compare tos to 0 118 6502 1527 jgt sTrue ; set true if tos>0 119 6504 1028 jmp sFalse ; else set result to false 120 ;] 121 122 ;[ U< u1 u2 -- flag 83 "u-less-than" 123 ; flag is true if u1 is less than u2. 124 6506 64F8 ulessh data gtzh,2 124 6508 0002 125 650A 553C text 'U<' 126 650C 650E uless data $+2 127 650E 8534 c *stack+,*stack ; compare u2 to u1. pop u2 128 6510 1B20 jh sTrue ; set true if u2>u1 129 6512 1021 jmp sFalse ; else set false 130 ;] 131 132 ;[ WITHIN ( n low high -- true|false ) 133 ; returns true if n is within low and high+1 134 6514 6506 withh data ulessh,6 134 6516 0006 135 6518 5749 text 'WITHIN' 135 651A 5448 135 651C 494E 136 651E 8320 within data docol,over,sub,rspush,sub,rspop,uless,exit 136 6520 61C8 136 6522 6326 136 6524 6290 136 6526 6326 136 6528 62AC 136 652A 650C 136 652C 832C 137 ;] 138 139 ;[ 0<= ( x -- flag ) 140 ; returns true if x<=0 141 652E 6514 ltezh data withh,3 141 6530 0003 142 6532 303C text '0<= ' 142 6534 3D20 143 6536 6538 ltez data $+2 144 6538 C514 mov *stack,*stack ; compare tos to 0 145 653A 110B jlt sTrue ; set true if tos<0 146 653C 130A jeq sTrue ; or if tos=0 147 653E 100B jmp sFalse ; else set result to false 148 ;] 149 150 ;[ 0>= ( x -- flag ) 151 ; returns true if x>=0 152 6540 652E gtezh data ltezh,3 152 6542 0003 153 6544 303E text '0>= ' 153 6546 3D20 154 6548 654A gtez data $+2 155 654A C514 mov *stack,*stack ; compare tos to 0 156 654C 1502 jgt sTrue ; set true if tos>0 157 654E 1301 jeq sTrue ; or if tos=0 158 6550 1002 jmp sFalse ; else set result to false 159 ;] 160 161 ; The following routines are common to all the routines above. 162 ; The first routine returns a true result, the second routine a false result. 163 ; Each routine has two entry points, depending on whether 1 or 2 parameters 164 ; should be removed from the stack. 165 166 ; called when the result of the comparison is true 167 6552 0714 sTrue seto *stack ; set value to -1 (true) 168 6554 045C b *next 169 170 ; called when the result of the comparison is false 171 6556 04D4 sFalse clr *stack ; set result to 0 (false) 172 6558 045C b *next * * COPY 'C:\TI\Source\TurboForth\Bank0\0-05-FlowControl.a99' * 1 ; ______ _ _____ _ _ 2 ; | ____| | / ____| | | | | 3 ; | |__ | | _____ __ | | ___ _ __ | |_ _ __ ___ | | 4 ; | __| | |/ _ \ \ /\ / / | | / _ \| '_ \| __| '__/ _ \| | 5 ; | | | | (_) \ V V / | |____| (_) | | | | |_| | | (_) | | 6 ; |_| |_|\___/ \_/\_/ \_____|\___/|_| |_|\__|_| \___/|_| 7 ; Flow control words 8 9 ; MARK & AHEAD: Utilities for flow control words 10 ; : MARK ( -- addr) HERE 0 , ; 11 655A 8320 mark data docol 12 655C 780E data ghere,lit0,comma 12 655E 6084 12 6560 70CC 13 6562 832C data exit 14 15 ; : AHEAD ( -- addr ) POSTPONE BRANCH MARK ; IMMEDIATE 16 6564 8320 ahead data docol 17 6566 7262 data compile,branch,mark 17 6568 65E4 17 656A 655A 18 656C 832C data exit 19 20 21 ;[ FOR ( loop_count -- ) 22 ; Implements FOR...NEXT looping as in COUNT FOR .. .. NEXT 23 ; I is available for retrieving the index. 24 ; : FOR ( start--) COMPILE LIT 0 , COMPILE SWAP [COMPILE] DO ; IMMEDIATE 25 656E 6540 forh data gtezh,immed+3 25 6570 8003 26 6572 464F text 'FOR ' 26 6574 5220 27 6576 8320 for data docol 28 6578 7262 data compile,lit0 28 657A 6084 29 657C 7262 data compile,swap,do1 29 657E 617C 29 6580 66DA 30 6582 832C data exit 31 ;] 32 33 ;[ NEXT 34 ; : NEXT ( --) COMPILE LIT -1 , [COMPILE] +LOOP ; IMMEDIATE 35 6584 656E nexth data forh,immed+4 35 6586 8004 36 6588 4E45 text 'NEXT' 36 658A 5854 37 658C 8320 fnext1 data docol 38 658E 609C data litm1,clc,ploop1 38 6590 60AC 38 6592 675A 39 6594 832C data exit 40 ;] 41 42 ; : IF ( -- addr ) POSTPONE ?BRANCH MARK ; IMMEDIATE 43 ;[ IF flag -- C,I,79 44 ; -- sys (compiling) 45 ; Used in the form: 46 ; flag IF ... ELSE ... THEN 47 ; or flag IF ... THEN 48 ; If flag is true, the words following IF are executed and the words following 49 ; ELSE until just after THEN are skipped. The ELSE part is optional. 50 ; If flag is false, the words from IF through ELSE , or from IF through THEN 51 ; (when no ELSE is used), are skipped. 52 ; sys is balanced with its corresponding ELSE or THEN . 53 ; See: "9.9 Control Structures" 54 6596 6584 ifh data nexth,immed+2 54 6598 8002 55 659A 4946 text 'IF' 56 659C 8320 if data docol 57 659E 70B2 data lit,ifcnt,refup 57 65A0 A07C 57 65A2 67BA 58 65A4 7262 data compile,zbrnch,mark 58 65A6 65F6 58 65A8 655A 59 65AA 832C data exit 60 ;] 61 62 ; : THEN HERE SWAP ! ; IMMEDIATE 63 ;[ THEN -- C,I,79 64 ; sys -- (compiling) 65 ; Used in the form: 66 ; flag IF ... ELSE ... THEN 67 ; or flag IF ... THEN 68 ; THEN is the point where execution continues after ELSE , or IF when no ELSE 69 ; is present. 70 ; sys is balanced with its corresponding IF or ELSE . See: IF ELSE 71 65AC 6596 thenh data ifh,immed+4 71 65AE 8004 72 65B0 5448 text 'THEN' 72 65B2 454E 73 65B4 8320 then data docol 74 65B6 70B2 data lit,ifcnt,refdn 74 65B8 A07C 74 65BA 67C2 75 65BC 780E data ghere,swap,store 75 65BE 617C 75 65C0 6852 76 65C2 832C data exit 77 ;] 78 79 ; : ELSE POSTPONE AHEAD SWAP POSTPONE THEN ; IMMEDIATE 80 ;[ ELSE -- C,I,79 81 ; sys1 -- sys2 (compiling) 82 ; Used in the form: 83 ; flag IF ... ELSE ... THEN 84 ; ELSE executes after the true part following IF . ELSE forces execution to 85 ; continue at just after THEN . sys1 is balanced with its corresponding IF . 86 ; sys2 is balanced with its corresponding THEN . See: IF THEN 87 65C4 65AC elseh data thenh,immed+4 87 65C6 8004 88 65C8 454C text 'ELSE' 88 65CA 5345 89 65CC 8320 else data docol 90 65CE 6564 data ahead,swap,ghere,swap,store 90 65D0 617C 90 65D2 780E 90 65D4 617C 90 65D6 6852 91 65D8 832C data exit 92 ;] 93 94 ;[ BRANCH ( -- ) 95 ; unconditional branch: e.g: BRANCH 4 will branch forwards four words. 96 ; Negative offsets supported. 97 65DA 65C4 brnchh data elseh,6 97 65DC 0006 98 65DE 4252 text 'BRANCH' 98 65E0 414E 98 65E2 4348 99 65E4 65E6 branch data $+2 100 ; at entry, R3 is pointing at the branch address... 101 65E6 C0D3 mov *pc,pc ; get the in-line address and move to the 102 65E8 045C b *next ; instruction pointer 103 104 ;] 105 106 ;[ 0BRANCH ( flag -- ) 107 ; Branch if data on the stack is 0. e.g: 0BRANCH 4 will branch forwards 4 108 ; bytes if the value on the data stack is 0 109 65EA 65DA zbrchh data brnchh,7 109 65EC 0007 110 65EE 3042 text '0BRANCH ' 110 65F0 5241 110 65F2 4E43 110 65F4 4820 111 65F6 83B4 zbrnch data _zbrnch ; code is in high-speed ram. 112 ; see 1-15-Initialise.a99 113 ;] 114 115 ;[ CASE..OF..ENDCASE ( -- ) 116 ; Part of CASE..OF..ENDCASE 117 ; CASE 118 65F8 65EA caseh data zbrchh,immed+4 118 65FA 8004 119 65FC 4341 text 'CASE' 119 65FE 5345 120 6600 8320 case data docol 121 6602 70B2 data lit,cascnt,refup ; reference count 121 6604 A082 121 6606 67BA 122 6608 6084 data lit0 123 660A 832C data exit 124 125 ; OF 126 660C 65F8 ofh data caseh,immed+2 126 660E 8002 127 6610 4F46 text 'OF' 128 6612 8320 of data docol 129 6614 70B2 data lit,ofcnt,refup 129 6616 A084 129 6618 67BA 130 661A 7262 data compile,over,compile,eq,if,compile,drop 130 661C 61C8 130 661E 7262 130 6620 647A 130 6622 659C 130 6624 7262 130 6626 6172 131 6628 832C data exit 132 133 ; ENDOF 134 662A 660C endofh data ofh,immed+5 134 662C 8005 135 662E 454E text 'ENDOF ' 135 6630 444F 135 6632 4620 136 6634 8320 endof data docol 137 6636 70B2 data lit,ofcnt,refdn,else 137 6638 A084 137 663A 67C2 137 663C 65CC 138 663E 832C data exit 139 140 ; ENDCASE 141 6640 662A endcah data endofh,immed+7 141 6642 8007 142 6644 454E text 'ENDCASE ' 142 6646 4443 142 6648 4153 142 664A 4520 143 664C 8320 endcas data docol 144 664E 70B2 data lit,cascnt,refdn ; reference count 144 6650 A082 144 6652 67C2 145 6654 7262 data compile,drop,qdup,zbrnch,$+8,then,branch,$-10 145 6656 6172 145 6658 61FC 145 665A 65F6 145 665C 6664 145 665E 65B4 145 6660 65E4 145 6662 6658 146 6664 832C data exit 147 ;] 148 149 ; : BEGIN HERE ; IMMEDIATE \ synonym purely for readability 150 ;[ BEGIN -- C,I,79 151 ; -- sys (compiling) 152 ; Used in the form: 153 ; BEGIN ... flag UNTIL 154 ; or BEGIN ... flag WHILE ... REPEAT 155 ; BEGIN marks the start of a word sequence for repetitive execution. 156 ; A BEGIN-UNTIL loop will be repeated until flag is true. 157 ; A BEGIN-WHILE-REPEAT will be repeated until flag is false. 158 ; The words after UNTIL or REPEAT will be executed when either loop is finished. 159 ; sys is balanced with its corresponding UNTIL or WHILE . 160 ; See: "9.9 Control Structures" 161 6666 6640 beginh data endcah,immed+5 161 6668 8005 162 666A 4245 text 'BEGIN ' 162 666C 4749 162 666E 4E20 163 6670 8320 begin data docol 164 6672 70B2 data lit,begcnt,refup 164 6674 A086 164 6676 67BA 165 6678 780E data ghere 166 667A 832C data exit 167 ;] 168 169 ; : UNTIL POSTPONE ?BRANCH , ; IMMEDIATE 170 ;[ UNTIL ( address -- ) 171 667C 6666 untilh data beginh,immed+5 171 667E 8005 172 6680 554E text 'UNTIL ' 172 6682 5449 172 6684 4C20 173 6686 8320 until data docol 174 6688 70B2 data lit,begcnt,refdn 174 668A A086 174 668C 67C2 175 668E 7262 data compile,zbrnch,comma 175 6690 65F6 175 6692 70CC 176 6694 832C data exit 177 ;] 178 179 ; : AGAIN POSTPONE BRANCH , ; IMMEDIATE 180 ;[ AGAIN ( address -- ) 181 6696 667C againh data untilh,immed+5 181 6698 8005 182 669A 4147 text 'AGAIN ' 182 669C 4149 182 669E 4E20 183 66A0 8320 again data docol 184 66A2 70B2 data lit,begcnt,refdn 184 66A4 A086 184 66A6 67C2 185 66A8 7262 data compile,branch,comma 185 66AA 65E4 185 66AC 70CC 186 66AE 832C data exit 187 ;] 188 189 ; : WHILE POSTPONE IF SWAP ; IMMEDIATE 190 ;[ WHILE flag -- C,I,79 191 ; sys1 -- sys2 (compiling) 192 ; Used in the form: 193 ; BEGIN ... flag WHILE ... REPEAT 194 ; Selects conditional execution based on flag. When flag is true, execution 195 ; continues to just after the WHILE through to the REPEAT which then continues 196 ; execution back to just after the BEGIN. 197 ; When flag is false, execution continues to just after the REPEAT, exiting the 198 ; control structure. 199 ; sys1 is balanced with its corresponding BEGIN. 200 ; sys2 is balanced with its corresponding REPEAT. See: BEGIN 201 66B0 6696 whileh data againh,immed+5 201 66B2 8005 202 66B4 5748 text 'WHILE ' 202 66B6 494C 202 66B8 4520 203 66BA 8320 while data docol 204 66BC 659C data if,swap 204 66BE 617C 205 66C0 832C data exit 206 ;] 207 208 ; : REPEAT POSTPONE AGAIN POSTPONE THEN ; IMMEDIATE 209 ;[ REPEAT -- C,I,79 210 ; sys -- (compiling) 211 ; Used in the form: 212 ; BEGIN ... flag WHILE ... REPEAT 213 ; At execution time, REPEAT continues execution to just after the corresponding 214 ; BEGIN. 215 ; sys is balanced with its corresponding WHILE. See: BEGIN 216 66C2 66B0 repeth data whileh,immed+6 216 66C4 8006 217 66C6 5245 text 'REPEAT' 217 66C8 5045 217 66CA 4154 218 66CC 8320 repeat data docol 219 66CE 66A0 data again,then 219 66D0 65B4 220 66D2 832C data exit 221 ;] 222 223 ;[ DO w1 w2 -- C,I,83 224 ; -- sys (compiling) 225 ; Used in the form: 226 ; DO ... LOOP 227 ; or DO ... +LOOP 228 ; Begins a loop which terminates based on control parameters. 229 ; The loop index begins at w2, and terminates based on the limit w1. 230 ; See LOOP and +LOOP for details on how the loop is terminated. 231 ; The loop is always executed at least once. 232 ; For example: w DUP DO ... LOOP executes 65,536 times. 233 ; sys is balanced with its corresponding LOOP or +LOOP . 234 ; See: "9.9 Control Structures" 235 ; note: DO is immediate and compiles a reference to (DO) 236 ; 237 ; Loop frame format: 238 ; 0 = current loop index <----- RSTACK points to this value 239 ; +2 = loop limit 240 ; +4 = loop exit address 241 ; To drop a loop frame, add 6 to RSTACK 242 ; 243 ; In words, for A B DO ... LOOP 244 ; (DO) puts three things on to the return stack 245 ; 1. the address of the word after LOOP - where execution continues when 246 ; the loop executes 247 ; 2. A + >8000 (A with its sign bit 'permuted') 248 ; 3. B minus the value computed at step 2 <-- top of return stack 249 ; 250 ; LOOP and +LOOP add 1 or whatever to the value at 3. 251 ; If the overflow flag is set, drop two elements from the return stack, 252 ; pop the final value from R (the address at 1. above) 253 ; into I and execute next. 254 ; 255 ; I becomes: 256 ; 4. Move the value at 2. above to the data stack 257 ; 5. Add the value at 3. above to the data stack 258 ; 259 66D4 66C2 do1h data repeth,immed+2 259 66D6 8002 260 66D8 444F text 'DO' 261 66DA 8320 do1 data docol 262 66DC 70B2 data lit,docnt,refup ; increase reference counters 262 66DE A07E 262 66E0 67BA 263 66E2 7262 data compile,do,ghere,lit0,comma ; compile (do) here 0 , 263 66E4 66F6 263 66E6 780E 263 66E8 6084 263 66EA 70CC 264 66EC 832C data exit 265 266 66EE 66D4 doh data do1h,4 266 66F0 0004 267 66F2 2844 text '(DO)' 267 66F4 4F29 268 66F6 66F8 do data $+2 269 66F8 C034 mov *stack+,r0 ; pop initial index 270 66FA C074 mov *stack+,r1 ; pop loop termination value 271 66FC 0221 ai r1,>8000 ; flip sign bit 271 66FE 8000 272 6700 6001 s r1,r0 ; calculate initial index 273 6702 0645 dect rstack ; new return stack entry 274 6704 C573 mov *pc+,*rstack ; loop exit address to return stack 275 6706 0645 dect rstack ; new return stack entry 276 6708 C541 mov r1,*rstack ; loop limit to return stack 277 670A 0645 dect rstack ; new return stack entry 278 670C C540 mov r0,*rstack ; loop index to return stack 279 670E 045C b *next 280 ;] 281 282 ;[ LOOP -- C,I,83 283 ; sys -- (compiling) 284 ; Increments the DO-LOOP index by one. If the new index was incremented across 285 ; the boundary between limit-1 and limit the loop is terminated and loop control 286 ; parameters are discarded. When the loop is not terminated, execution 287 ; continues to just after the corresponding DO. 288 ; sys is balanced with its corresponding DO . See: DO 289 ; note: LOOP is immediate and compiles a reference to (LOOP) 290 6710 66EE loop1h data doh,immed+4 290 6712 8004 291 6714 4C4F text 'LOOP' 291 6716 4F50 292 6718 8320 loop1 data docol 293 671A 70B2 data lit,docnt,refdn ; reduce DO/LOOP reference counters 293 671C A07E 293 671E 67C2 294 6720 6186 data dup,compile,loop 294 6722 7262 294 6724 673E 295 6726 780E loop2 data ghere,plus2,swap,store,plus2,comma 295 6728 62CE 295 672A 617C 295 672C 6852 295 672E 62CE 295 6730 70CC 296 6732 832C data exit 297 298 6734 6710 looph data loop1h,6 298 6736 0006 299 6738 284C text '(LOOP)' 299 673A 4F4F 299 673C 5029 300 673E 6740 loop data $+2 301 6740 0595 inc *rstack ; increment loop count 302 6742 1904 loopchk jno lagain ; if no overflow then loop again 303 6744 0225 loopx ai rstack,6 ; otherwise pop loop frame 303 6746 0006 304 6748 05C3 inct pc ; move past (LOOP)'s in-line parameter 305 674A 045C b *next 306 674C C0D3 lagain mov *pc,pc ; reload loop address 307 674E 045C b *next 308 ;] 309 310 ;[ +LOOP n -- C,I,83 "plus-loop" 311 ; sys -- (compiling) 312 ; n is added to the loop index. If the new index was incremented across the 313 ; boundary between limit-1 and limit then the loop is terminated and loop 314 ; control parameters are discarded. When the loop is not terminated, execution 315 ; continues to just after the corresponding DO. 316 ; sys is balanced with its corresponding DO. See: DO 317 ; note: +LOOP is immediate and compiles a reference to (+LOOP) 318 6750 6734 plooh1 data looph,immed+5 318 6752 8005 319 6754 2B4C text '+LOOP ' 319 6756 4F4F 319 6758 5020 320 675A 8320 ploop1 data docol 321 675C 70B2 data lit,docnt,refdn 321 675E A07E 321 6760 67C2 322 6762 6186 data dup,compile,ploop,branch,loop2 ; compile (+LOOP) then as (LOOP) 322 6764 7262 322 6766 6778 322 6768 65E4 322 676A 6726 323 324 676C 6750 plooph data plooh1,7 324 676E 0007 325 6770 282B text '(+LOOP) ' 325 6772 4C4F 325 6774 4F50 325 6776 2920 326 6778 677A ploop data $+2 327 677A A574 a *stack+,*rstack ; pop increment and add to index on return stack 328 677C 10E2 jmp loopchk 329 ;] 330 331 ;[ LEAVE -- C,I,83 332 ; -- (compiling) 333 ; Transfers execution to just beyond the next LOOP or +LOOP . 334 ; The loop is terminated and loop control parameters are discarded. 335 ; May only be used in the form: 336 ; DO ... LEAVE ... LOOP 337 ; or DO ... LEAVE ... +LOOP 338 ; LEAVE may appear within other control structures which are nested within the 339 ; do-loop structure. More than one LEAVE may appear within a do-loop. 340 ; See: "9.3 Return Stack" 341 ; Note: LEAVE *must* appear within an IF ... THEN block for correct operation. 342 677E 676C leaveh data plooph,5 342 6780 0005 343 6782 4C45 text 'LEAVE ' 343 6784 4156 343 6786 4520 344 6788 678A leave data $+2 345 678A C0E5 mov @4(rstack),pc ; load pc with exit address 345 678C 0004 346 678E 0225 ai rstack,6 ; pop loop frame from return stack 346 6790 0006 347 6792 045C b *next 348 ;] 349 350 ;[ I -- w C,79 351 ; w is a copy of the loop index. May only be used in the 352 ; form: 353 ; DO ... I ... LOOP 354 ; or DO ... I ... +LOOP 355 ; or FOR .. I ... NEXT 356 6794 677E getih data leaveh,1 356 6796 0001 357 6798 4920 text 'I ' 358 679A 679C geti data $+2 359 679C 0644 dect stack ; new data stack entry 360 679E C525 mov @2(rstack),*stack ; place index on data stack 360 67A0 0002 361 67A2 A515 a *rstack,*stack ; adjust 362 67A4 045C b *next 363 ;] 364 365 ;[ J -- w C,79 366 ; w is a copy of the index of the next outer loop. 367 ; May only be used within a nested DO-LOOP or DO-+LOOP in the form, for example: 368 ; DO ... DO ... J ... LOOP ... +LOOP 369 ; Also active in nested FOR...NEXT loops. 370 67A6 6794 getjh data getih,1 370 67A8 0001 371 67AA 4A20 text 'J ' 372 67AC 67AE getj data $+2 373 67AE 0644 dect stack ; new data stack entry 374 67B0 C525 mov @8(rstack),*stack ; place outer loop index on data stack 374 67B2 0008 375 67B4 A525 a @6(rstack),*stack ; adjust 375 67B6 0006 376 67B8 045C b *next 377 ;] 378 379 ;[ utility routines for reference counting 380 67BA 67BC refup data $+2 381 67BC C034 mov *stack+,r0 ; pop address of reference counter 382 67BE 0590 inc *r0 ; increase reference counter 383 67C0 045C b *next 384 385 67C2 67C4 refdn data $+2 386 67C4 C034 mov *stack+,r0 ; pop address of reference of counter 387 67C6 0610 dec *r0 ; decrease reference counter 388 67C8 045C b *next 389 ;] * * COPY 'C:\TI\Source\TurboForth\Bank0\0-06-Logical.a99' * 1 ; _ _ _ __ __ _ 2 ; | | (_) | | \ \ / / | | 3 ; | | ___ __ _ _ ___ __ _| | \ \ /\ / /___ _ __ __| |___ 4 ; | | / _ \ / _` | |/ __|/ _` | | \ \/ \/ // _ \| '__/ _` / __| 5 ; | |____| (_) | (_| | | (__| (_| | | \ /\ /| (_) | | | (_| \__ \ 6 ; |______|\___/ \__, |_|\___|\__,_|_| \/ \/ \___/|_| \__,_|___/ 7 ; __/ | 8 ; |___/ 9 ; 10 ;[ AND 16b1 16b2 -- 16b3 79 11 ; 16b3 is the bit-by-bit logical 'and' of 16b1 with 16b2. 12 67CA 67A6 andh data getjh,3 12 67CC 0003 13 67CE 414E text 'AND ' 13 67D0 4420 14 67D2 67D4 and data $+2 15 67D4 0554 inv *stack ; invert 16b2 for SZC instruction 16 ; (see ED/AS manual, page 190) 17 67D6 4534 szc *stack+,*stack ; perform AND function and pop 16b2 18 67D8 045C b *next 19 ;] 20 21 ;[ OR 16b1 16b2 -- 16b3 79 22 ; 16b3 is the bit-by-bit inclusive-or of 16b1 with 16b2. 23 67DA 67CA orh data andh,2 23 67DC 0002 24 67DE 4F52 text 'OR' 25 67E0 67E2 or_ data $+2 26 67E2 E534 soc *stack+,*stack ; or 16b2 and 16b1. pop 16b2 27 67E4 045C b *next 28 ;] 29 30 ;[ XOR 16b1 16b2 -- 16b3 79 "x-or" 31 ; 16b3 is the bit-by-bit exclusive-or of 16b1 with 16b2. 32 67E6 67DA xorh data orh,3 32 67E8 0003 33 67EA 584F text 'XOR ' 33 67EC 5220 34 67EE 67F0 xor_ data $+2 35 67F0 C234 mov *stack+,r8 ; pop 16b2 in r8 36 67F2 2A14 xor *stack,r8 ; xor 16b1 with 16b2. result in r8 37 67F4 C508 mov r8,*stack ; result to TOS 38 ; (what a total shitter that I can't do a simple XOR *STACK+,*STACK ) 39 67F6 045C b *next 40 ;] 41 42 ;[ NOT 16b1 -- 16b2 83 43 ; 16b2 is the one's complement of 16b1. 44 67F8 67E6 invh data xorh,3 44 67FA 0003 45 67FC 4E4F text 'NOT ' 45 67FE 5420 46 6800 6802 inv_ data $+2 47 6802 0554 inv *stack ; invert the word on TOS 48 6804 045C b *next 49 ;] 50 51 ;[ << (bitwise) ( x count -- x ) 52 ; left shift x count bits (arithmetic shift) 53 6806 67F8 lsfth data invh,2 53 6808 0002 54 680A 3C3C text '<<' 55 680C 680E lsft data $+2 56 680E C034 mov *stack+,r0 ; pop shift count into r0 57 6810 C214 mov *stack,r8 ; x 58 6812 0A08 sla r8,r0 ; shift x by r0 bits 59 6814 C508 mov r8,*stack ; result back onto stack 60 6816 045C b *next 61 ;] 62 63 ;[ >> ( x count -- x ) 64 ; right shift x count bits (logical shift) 65 6818 6806 rsfth data lsfth,2 65 681A 0002 66 681C 3E3E text '>>' 67 681E 6820 rsft data $+2 68 6820 C034 mov *stack+,r0 ; pop shift count into r0 69 6822 C214 mov *stack,r8 ; x 70 6824 0908 srl r8,r0 ; shift x by r0 bits 71 6826 C508 mov r8,*stack ; result back onto stack 72 6828 045C b *next 73 ;] * * COPY 'C:\TI\Source\TurboForth\Bank0\0-07-Memory.a99' * 1 ; __ __ 2 ; | \/ | /\ 3 ; | \ / | ___ _ __ ___ ___ _ __ _ _ / \ ___ ___ ___ ___ ___ 4 ; | |\/| |/ _ \ '_ ` _ \ / _ \| '__| | | | / /\ \ / __|/ __|/ _ | __/ __| 5 ; | | | | __/ | | | | | (_) | | | |_| | / ____ \ (__| (__| __|__ \__ \ 6 ; |_| |_|\___|_| |_| |_|\___/|_| \__, | /_/ \_\___|\___|\___|___/___/ 7 ; Memory access words __/ | 8 ; |___/ 9 10 0000 9C02 grmwa equ >9c02 ; GROM Write Address Register 11 0000 9802 grmra equ >9802 ; GROM Read Address Register 12 0000 9800 grmrd equ >9800 ; GROM Read Data Register 13 0000 9C00 grmwd equ >9c00 ; GROM Write Data Register 14 15 ;[ @ addr -- 16b 79 "fetch" 16 ; 16b is the value at addr. 17 682A 6818 fetchh data rsfth,1 17 682C 0001 18 682E 4020 text '@ ' 19 6830 6832 fetch data $+2 20 6832 C214 mov *stack,r8 ; get address 21 6834 C518 mov *r8,*stack ; peek address and put on data stack 22 6836 045C b *next 23 ;] 24 25 ;[ @++ ( addr -- addr+2 value ) 26 ; fetches the cell at memory address "address" then increments address 27 ; and leaves it on the stack 28 6838 682A faddph data fetchh,3 28 683A 0003 29 683C 402B text '@++' 29 683E 2B 30 683F 0000 EVEN *>>> Assembler Auto-Generated <<< 31 6840 6842 ftchpp data $+2 32 6842 C214 mov *stack,r8 ; get addr 33 6844 05D4 inct *stack ; advance addr to get addr+2 34 6846 0644 dect stack ; new stack entry 35 6848 C518 mov *r8,*stack ; peek address and value put on data stack 36 684A 045C b *next 37 ;] 38 39 ;[ ! 16b addr -- 79 "store" 40 ; 16b is stored at addr. 41 684C 6838 storeh data faddph,1 41 684E 0001 42 6850 2120 text '! ' 43 6852 6854 store data $+2 44 6854 C234 mov *stack+,r8 ; pop addr 45 6856 C634 mov *stack+,*r8 ; pop 16b and write to addr 46 6858 045C b *next 47 ;] 48 49 ;[ +! w1 addr -- 79 "plus-store" 50 ; w1 is added to the w value at addr using the convention for + . 51 ; This sum replaces the original value at addr. 52 685A 684C staddh data storeh,2 52 685C 0002 53 685E 2B21 text '+!' 54 6860 6862 stadd data $+2 55 6862 C234 mov *stack+,r8 ; pop addr 56 6864 A634 a *stack+,*r8 ; pop w1 and add to value at addr 57 6866 045C b *next 58 ;] 59 60 ;[ C@ addr -- 8b 79 "c-fetch" 61 ; 8b is the contents of the byte at addr. 62 6868 685A chrfh data staddh,2 62 686A 0002 63 686C 4340 text 'C@' 64 686E 6870 chrftc data $+2 65 6870 C214 mov *stack,r8 ; address in r8 66 6872 D218 movb *r8,r8 ; peek address and store in msb of r8 67 6874 0988 srl r8,8 ; move to low byte 68 6876 C508 mov r8,*stack ; move msb of r8 onto data stack 69 6878 045C b *next 70 ;] 71 72 ;[ C! 16b addr -- 79 "c-store" 73 ; The least-significant 8 bits of 16b are stored into the byte at addr. 74 687A 6868 stbh data chrfh,2 74 687C 0002 75 687E 4321 text 'C!' 76 6880 6882 stb data $+2 77 6882 C234 mov *stack+,r8 ; pop addr 78 6884 C1F4 mov *stack+,r7 ; pop 16b 79 6886 06C7 swpb r7 ; rotate LOW BYTE into MSB 80 6888 D607 movb r7,*r8 ; move the byte into the address in r8 81 688A 045C b *next 82 ;] 83 84 ;[ 0! ( addr -- ) 85 ; store 0 at addr 86 688C 687A stor0h data stbh,2 86 688E 0002 87 6890 3021 text '0!' 88 6892 6894 store0 data $+2 89 6894 C234 mov *stack+,r8 ; pop address 90 6896 04D8 clr *r8 ; zero it 91 6898 045C stor0x b *next 92 ;] 93 94 ;[ CHARS ( x1 -- x1 ) 95 ; return the memory size required to hold x2 chars (bytes) 96 ; note: since this word does nothing, it is immediate, to avoid a run-time 97 ; speed penalty 98 689A 688C charsh data stor0h,immed+5 98 689C 8005 99 689E 4348 text 'CHARS ' 99 68A0 4152 99 68A2 5320 100 68A4 6898 chars data stor0x ; do nothing, and use the exit in 0! to do it! 101 ; (saves 2 bytes) 102 ;] 103 104 ;[ V@ ( address -- value ) 105 ; read vdp address and return BYTE as 16 bit right justified cell 106 68A6 689A vdpfh data charsh,2 106 68A8 0002 107 68AA 5640 text 'V@' 108 68AC 68AE vdpftc data $+2 109 68AE C014 mov *stack,r0 ; vdp address from data stack to r0 110 68B0 06A0 bl @vsbr ; execute VDP single byte read routine 110 68B2 7F60 111 68B4 0981 srl r1,8 ; value move to low byte 112 68B6 C501 mov r1,*stack ; place it on the stack 113 68B8 045C b *next 114 ;] 115 116 ;[ V! ( value addr -- ) 117 ; store BYTE value (as 16 bit right justified cell) at VDP address 118 68BA 68A6 vdpwh data vdpfh,2 118 68BC 0002 119 68BE 5621 text 'V!' 120 68C0 68C2 vdpstr data $+2 121 68C2 C034 mov *stack+,r0 ; pop addr 122 68C4 C074 mov *stack+,r1 ; pop value 123 68C6 06C1 swpb r1 ; get lsb of value into msb 124 68C8 06A0 bl @vsbw ; write to vdp 124 68CA 7F9A 125 68CC 045C b *next 126 ;] 127 128 ;[ VDP Write Word ( address value -- ) 129 68CE 68BA vdpwwh data vdpwh,3 129 68D0 0003 130 68D2 5632 text 'V2! ' 130 68D4 2120 131 68D6 8320 data docol,swap,vdpww,drop,exit 131 68D8 617C 131 68DA 7D58 131 68DC 6172 131 68DE 832C 132 ;] 133 134 ;[ VDP Read Word 135 ; : V2@ ( vdp_address -- word_value) 136 ; DUP V@ >< SWAP 1+ V@ OR ; 137 68E0 68CE vdprwh data vdpwwh,3 137 68E2 0003 138 68E4 5632 text 'V2@ ' 138 68E6 4020 139 68E8 8320 vdprw data docol,dup,vdpftc,swpb_,swap,plus1,vdpftc,or_,exit 139 68EA 6186 139 68EC 68AC 139 68EE 6220 139 68F0 617C 139 68F2 62BA 139 68F4 68AC 139 68F6 67E0 139 68F8 832C 140 ;] 141 142 ;[ VMBR ( vdp_address cpu_address byte_count -- ) 143 68FA 68E0 vmbrh data vdprwh,4 143 68FC 0004 144 68FE 564D text 'VMBR' 144 6900 4252 145 6902 6904 fvmbr data $+2 146 6904 0206 li r6,vmbr ; address of vdp routine to call 146 6906 7F82 147 6908 1007 jmp vdpm 148 ;] 149 150 ;[ VMBW ( vdp_address cpu_address byte_count -- ) 151 690A 68FA vmbwh data vmbrh,4 151 690C 0004 152 690E 564D text 'VMBW' 152 6910 4257 153 6912 6914 fvmbw data $+2 154 6914 0206 li r6,vmbw ; address of vdp routine to call 154 6916 7FC2 155 ; fall down to vdpm routine below... 156 ;] 157 158 ;[ utility routine used by VMBR & VMBW above 159 vdpm 160 6918 C0B4 mov *stack+,r2 ; pop byte count 161 691A C074 mov *stack+,r1 ; pop cpu address 162 691C C034 mov *stack+,r0 ; pop vdp address 163 691E C082 mov r2,r2 ; check for zero byte count 164 6920 1301 jeq vdpx ; if zero then just exit 165 6922 0696 bl *r6 ; execute appropriate routine 166 6924 045C vdpx b *next 167 ;] 168 169 ;[ ; >MAP ( bank address -- ) 170 ; If a SAMS card is present, maps memory bank "bank" to address "address" 171 6926 690A samsh data vmbwh,4 171 6928 0004 172 692A 3E4D text '>MAP' 172 692C 4150 173 692E 6930 sams_ data $+2 174 6930 06A0 bl @bank1 174 6932 8332 175 6934 65FE data _sams ; implemented in 1-04-Memory.a99 176 ;] 177 178 ;[ HFREE ( -- free_bytes ) 179 ; returns the number of free bytes in upper 24k RAM 180 6936 6926 hfreeh data samsh,5 180 6938 0005 181 693A 4846 text 'HFREE ' 181 693C 5245 181 693E 4520 182 6940 8320 hfree data docol,lit,>ffff,ffaih,fetch,sub,plus1,exit 182 6942 70B2 182 6944 FFFF 182 6946 7750 182 6948 6830 182 694A 6326 182 694C 62BA 182 694E 832C 183 ;] 184 185 ;[ LFREE ( -- free_bytes ) 186 ; returns the number of free bytes in lower 8k RAM 187 6950 6936 lfreeh data hfreeh,5 187 6952 0005 188 6954 4C46 text 'LFREE ' 188 6956 5245 188 6958 4520 189 695A 8320 lfree data docol,lit 189 695C 70B2 190 695E 4000 bit1 data >4000 ; note: also used by VSBW to save 2 bytes 191 ; yes! memory is THAT tight! 192 6960 7766 data ffaml,fetch,sub,exit 192 6962 6830 192 6964 6326 192 6966 832C 193 ;] 194 195 ;[ FILL addr u 8b -- 83 196 ; u bytes of memory beginning at addr are set to 8b. 197 ; No action is taken if u is zero. 198 6968 6950 fillh data lfreeh,4 198 696A 0004 199 696C 4649 text 'FILL' 199 696E 4C4C 200 6970 6972 fill data $+2 201 6972 06A0 bl @bank1 201 6974 8332 202 6976 65AE data _fill ; implemented in 1-04-Memory.a99 203 ;] 204 205 ;[ CMOVE addr1 addr2 u -- 83 "c-move" 206 ; Move u bytes beginning at address addr1 to addr2. 207 ; The byte at addr1 is moved first, proceeding toward high memory. 208 ; If u is zero nothing is moved. 209 6978 6968 cmoveh data fillh,5 209 697A 0005 210 697C 434D text 'CMOVE ' 210 697E 4F56 210 6980 4520 211 6982 6984 cmove data $+2 212 6984 06A0 bl @bank1 212 6986 8332 213 6988 65C0 data _cmove ; implemented in 1-04-Memory.a99 214 ;] 215 216 ;[ CMOVE> addr1 addr2 u -- 83 "c-move-up" 217 ; Move the u bytes at address addr1 to addr2. 218 ; The move begins by moving the byte at (addr1 plus u minus 1) to 219 ; (addr2 plus u minus 1) and proceeds to successively lower addresses for u 220 ; bytes. 221 ; If u is zero nothing is moved. Useful for sliding a string towards higher 222 ; addresses. 223 698A 6978 cmovfh data cmoveh,6 223 698C 0006 224 698E 434D text 'CMOVE>' 224 6990 4F56 224 6992 453E 225 6994 6996 cmovf data $+2 226 6996 06A0 bl @bank1 226 6998 8332 227 699A 65D0 data _cmovf ; implemented in 1-04-Memory.a99 228 ;] 229 230 ;[ MEM ( -- ) 231 ; Displays the number of free bytes in low memory, high memory, and the total 232 ; number of free bytes to the screen. 233 699C 698A freeh data cmovfh,3 233 699E 0003 234 69A0 4D45 text 'MEM ' 234 69A2 4D20 235 69A4 8320 data docol 236 69A6 6940 data hfree,lfree,dup2,udot,udot,add,udot,exit 236 69A8 695A 236 69AA 75EE 236 69AC 782C 236 69AE 782C 236 69B0 631E 236 69B2 782C 236 69B4 832C 237 ;] 238 239 ;[ COPYW (source destination count -- ) 240 ; copy WORDS from source to destination for 'count' words 241 ; no action taken if count=0 242 69B6 699C copywh data freeh,5 242 69B8 0005 243 69BA 434F text 'COPYW ' 243 69BC 5059 243 69BE 5720 244 69C0 69C2 copyw data $+2 245 69C2 06A0 bl @bank1 245 69C4 8332 246 69C6 65EE data _copyw ; implemented in 1-04-Memory.a99 247 ;] 248 * * COPY 'C:\TI\Source\TurboForth\Bank0\0-08-Parsing.a99' * 1 ; _____ _ __ __ _ 2 ; | __ \ (_) \ \ / / | | 3 ; | |__) |__ _ _ __ ___ _ _ __ __ _ \ \ /\ / /___ _ __ __| |___ 4 ; | ___// _` | '__/ __| | '_ \ / _` | \ \/ \/ // _ \| '__/ _` / __| 5 ; | | | (_| | | \__ \ | | | | (_| | \ /\ /| (_) | | | (_| \__ \ 6 ; |_| \__,_|_| |___/_|_| |_|\__, | \/ \/ \___/|_| \__,_|___/ 7 ; __/ | 8 ; |___/ 9 ; Dictionary lookup and associated parsing words 10 11 ;[ EXPECT addr +n -- M,83 12 ; Receive characters and store each into memory. The transfer begins at addr 13 ; proceeding towards higher addresses one byte per character until either a 14 ; "return" is received or until +n characters have been transferred. 15 ; No more than +n characters will be stored. 16 ; The "return" is not stored into memory. 17 ; No characters are received or transferred if +n is zero. 18 ; All characters actually received and stored into memory will be displayed, 19 ; with the "return" displaying as a space. See: SPAN "9.5.2 EXPECT" 20 69C8 69B6 expcth data copywh,6 20 69CA 0006 21 69CC 4558 text 'EXPECT' 21 69CE 5045 21 69D0 4354 22 69D2 69D4 expect data $+2 23 69D4 04E0 clr @in ; clear >IN variable 23 69D6 A042 24 69D8 04CE clr r14 ; counter for number of characters 25 ; *actually* in the buffer 26 69DA C374 mov *stack+,r13 ; pop length in r13 27 69DC C2B4 mov *stack+,r10 ; pop address address in r10 28 69DE C34D mov r13,r13 ; check length 29 69E0 133E jeq zchars ; quit if 0 characters requested 30 69E2 06A0 expnxt bl @kscn ; scan keyboard (wait for a keypress) 30 69E4 6DE2 31 ; ascii code returned on the stack 32 ; check for enter key... 33 69E6 8814 c *stack,@datCR ; compare to carriage return (enter key) 33 69E8 6A64 34 69EA 1337 jeq exp2 ; exit routine if enter was pressed 35 ;[ ; check for backspace key... 36 69EC 8814 c *stack,@lit8+4 ; compare to backspace key 36 69EE 6098 37 69F0 161F jne skipbs ; skip if backspace not pressed 38 69F2 05C4 inct stack ; remove backspace from stack 39 69F4 C38E mov r14,r14 ; check if anything in the buffer 40 69F6 13F5 jeq expnxt ; tib is empty, ignore... 41 ; do backspace... 42 69F8 06A0 bl @ccp ; compute cursor position 42 69FA 6F14 43 69FC 0201 li r1,>2000 ; load a space character 43 69FE 2000 44 6A00 06A0 bl @vsbw ; erase the cursor 44 6A02 7F9A 45 6A04 C020 mov @scrX,r0 ; get current x position 45 6A06 A028 46 6A08 160B jne back1 ; if x>0 we don't need to move up one line 47 6A0A C820 mov @xmax,@scrX ; move to end of line 47 6A0C A02C 47 6A0E A028 48 6A10 0620 dec @scrX ; correct X 48 6A12 A028 49 6A14 0620 dec @scrY ; up one screen line 49 6A16 A02A 50 6A18 C020 mov @scrY,r0 ; check y 50 6A1A A02A 51 6A1C 1106 jlt bumpY ; if <0 then reset to 0 52 6A1E 1002 jmp back2 53 6A20 0620 back1 dec @scrX ; move back one character 53 6A22 A028 54 6A24 060E back2 dec r14 ; decrement buffer index pointer 55 6A26 060A dec r10 ; decrement buffer position 56 6A28 10DC jmp expnxt ; get another keypress 57 6A2A 05A0 bumpY inc @scrY ; prevent Y from going <0 57 6A2C A02A 58 6A2E 10FA jmp back2 59 ;] 60 ; process keypress... 61 6A30 0644 skipbs dect stack ; new stack entry 62 6A32 C524 mov @2(stack),*stack ; duplicate value on stack for EMIT 62 6A34 0002 63 6A36 06A0 bl @emit_ ; call emit (which may/may not call SCRLUP) 63 6A38 6DA0 64 6A3A 06D4 swpb *stack ; shift ascii code into MSB 65 6A3C C074 mov *stack+,r1 66 6A3E C00A mov r10,r0 67 6A40 058A inc r10 68 6A42 06A0 bl @vsbw0 68 6A44 7FA8 69 6A46 058E inc r14 ; increment 'number of characters in buffer so far' 70 ; counter 71 6A48 880E c r14,@tibsiz ; do we have #TIB characters in the buffer? 71 6A4A A04A 72 6A4C 1302 jeq exp1 ; if so, exit the routine 73 6A4E 838D c r13,r14 ; have we got 'length' characters? 74 6A50 16C8 jne expnxt ; read another key if not 75 6A52 C80E exp1 mov r14,@_span ; move character count into _span 75 6A54 A04C 76 6A56 0460 b @space1+2 ; type a space to the console and exit 76 6A58 6D3A 77 6A5A 05C4 exp2 inct stack ; pop ascii 13 off the stack 78 6A5C 10FA jmp exp1 79 80 ; special case if 0 characters were requested for some weird reason... 81 6A5E 04E0 zchars clr @_span 81 6A60 A04C 82 6A62 045C b *next 83 6A64 000D datCR data 13 ; ascii code for carriage return 84 ;] 85 86 ;[ Comments: ( \ & .( 87 ; Allows comments e.g. : 1TO3 ( comment) 1 2 3 ; 88 ; Reads through the TIB until ) is found or end of line 89 6A66 69C8 remh data expcth,immed+1 89 6A68 8001 90 6A6A 2820 text '( ' 91 6A6C 8320 rem data docol 92 6A6E 70B2 data lit,')',word,drop2 92 6A70 0029 92 6A72 6AA2 92 6A74 75E0 93 6A76 832C data exit 94 95 6A78 6A66 trcomh data remh,immed+1 95 6A7A 8001 96 6A7C 5C20 text '\ ' 97 6A7E 6A80 trcom data $+2 98 6A80 06A0 bl @bank1 98 6A82 8332 99 6A84 6B9A data _trcom 100 101 6A86 6A78 typcmh data trcomh,immed+2 101 6A88 8002 102 6A8A 2E28 text '.(' 103 6A8C 8320 data docol,lit,41,word,type,cr,exit 103 6A8E 70B2 103 6A90 0029 103 6A92 6AA2 103 6A94 6C94 103 6A96 6E92 103 6A98 832C 104 ;] 105 106 ;[ WORD ( delimiter -- address length ) 107 ; Moves through TIB in VDP memory, discarding leading delimiters, looking for 108 ; a word. A word is identified when a trailing delimiter is detected. 109 ; The word is copied from VDP to CPU memory. 110 ; Pushes the start address of the word (in CPU memory), and the length of 111 ; the word to the stack. 112 ; If no word is found (for example if we hit the end of the TIB without 113 ; detecting a word then 0 0 is pushed on the stack. 114 115 6A9A 6A86 wordh data typcmh,4 115 6A9C 0004 116 6A9E 574F text 'WORD' 116 6AA0 5244 117 6AA2 8320 word data docol 118 ; tib @ blk @ ?dup if nip block then 119 6AA4 773E data tib_,fetch 119 6AA6 6830 120 6AA8 7B4E word0 data blk,fetch,qdup,zbrnch,word2,nip,fblock 120 6AAA 6830 120 6AAC 61FC 120 6AAE 65F6 120 6AB0 6AB6 120 6AB2 61D2 120 6AB4 7C52 121 6AB6 6ABA word2 data word1 122 6AB8 832C data exit 123 124 ; at this point, data stack is ( delimeter address -- ) 125 ; where address is the address in vdp to start searching from. 126 ; address is either TIB+>IN (if BLK=0) or block address+>IN 127 ; if BLK>0. (the code to add >IN to the address is in _word) 128 6ABA 6ABC word1 data $+2 129 6ABC 06A0 bl @bank1 129 6ABE 8332 130 6AC0 6B1A data _word ; see 1-08-Parsing.a99 131 ;] 132 133 ;[ BL ( -- 32 ) 134 ; pushes 32 decimal to the stack. BL is short for 'BLANK' often used in with 135 ; word to specify the delimeter: e.g. BL WORD 136 6AC2 6A9A blh data wordh,2 136 6AC4 0002 137 6AC6 424C text 'BL' 138 6AC8 8320 bl_ data docol,lit,32,exit 138 6ACA 70B2 138 6ACC 0020 138 6ACE 832C 139 ;] 140 141 ;[ FIND addr1 len -- addr2 n 83 142 ; addr1 is the address of a string. The string contains a word name to be 143 ; located in the currently active search order. If the word is not found, addr2 144 ; is the string address addr1, and n is zero. 145 ; If the word is found, addr2 is the compilation address and n is set to one of 146 ; two non-zero values. If the word found has the immediate attribute, 147 ; n is set to one. If the word is non-immediate, n is set to minus one (true). 148 ; Len indicates the length of the string beginnig at addr1. 149 6AD0 6AC2 findh data blh,4 149 6AD2 0004 150 6AD4 4649 text 'FIND' 150 6AD6 4E44 151 6AD8 8320 find data docol,lit,fndvec,fetch,execut,exit 151 6ADA 70B2 151 6ADC A006 151 6ADE 6830 151 6AE0 72AA 151 6AE2 832C 152 6AE4 6AE6 vfind data $+2 ; vectored find 153 6AE6 C1B4 mov *stack+,r6 ; pop length to r6 154 6AE8 C1E0 mov @latest,r7 ; get address of last dictionary entry 154 6AEA A044 155 6AEC C227 fndnxt mov @2(r7),r8 ; length of dictionary entry 155 6AEE 0002 156 6AF0 0248 andi r8,>400f ; mask out immediate bit and block numbers 156 6AF2 400F 157 6AF4 8188 c r8,r6 ; are they the same length? 158 6AF6 1303 jeq lmatch ; jump if yes 159 6AF8 C1D7 find1 mov *r7,r7 ; point to next dictionary entry 160 6AFA 1326 jeq nomatch ; if 0 then no match. end of dictionary. 161 6AFC 10F7 jmp fndnxt ; else check the next entry 162 ; the length matches. 163 ; now do a character comparison between the word in the buffer and the word 164 ; in the dictionary 165 6AFE C287 lmatch mov r7,r10 166 6B00 022A ai r10,4 ; point to text of dictionary entry 166 6B02 0004 167 6B04 C014 mov *stack,r0 ; buffer address in r0 168 6B06 D070 cnxtch movb *r0+,r1 ; otherwise get a character from buffer 169 6B08 06A0 bl @caschk ; convert case if case sensitive=off 169 6B0A 6B4E 170 6B0C C381 mov r1,r14 ; save the character 171 6B0E D07A movb *r10+,r1 ; get character from dictionary entry 172 6B10 06A0 bl @caschk ; convert case if case sensitive=off 172 6B12 6B4E 173 6B14 9381 find2 cb r1,r14 ; compare the two characters 174 6B16 16F0 jne find1 ; if not equal then check next dict entry 175 6B18 0608 dec r8 ; decrememnt length 176 6B1A 16F5 jne cnxtch ; if not 0 then check next character 177 ; we have a match push cfa and word type 178 6B1C C227 mov @2(r7),r8 ; get length of dictionary entry 178 6B1E 0002 179 6B20 C248 mov r8,r9 ; make a copy 180 6B22 0248 andi r8,>f ; retain length only 180 6B24 000F 181 6B26 A1C8 a r8,r7 ; add length 182 6B28 0227 ai r7,4 ; take account of address & link field 182 6B2A 0004 183 6B2C 0587 inc r7 ; round up... 184 6B2E 0247 andi r7,>fffe ; ...to even address 184 6B30 FFFE 185 6B32 C507 mov r7,*stack ; push cfa 186 6B34 0644 dect stack ; prepare to push 'n' (see stack sig) 187 6B36 0249 l8000 andi r9,immed ; check immediate bit 187 6B38 8000 188 6B3A 1304 jeq noimm ; if not set then push -1 for status 189 6B3C 0201 li r1,1 ; else push a 1 189 6B3E 0001 190 6B40 C501 mov r1,*stack 191 6B42 045C b *next 192 6B44 0714 noimm seto *stack ; not immediate - push -1 193 6B46 045C b *next 194 6B48 0644 nomatch dect stack ; leave address unchanged on stack 195 6B4A 04D4 clr *stack ; 0=not found 196 6B4C 045C b *next 197 ; Convert lower case characters to upper case if case sensitivity is turned off 198 ; Input: r1 msb = character to test 199 ; Output: r1 msb = upper case character 200 6B4E D360 caschk movb @cassen,r13 ; case sensitive mode switched off? 200 6B50 A056 201 6B52 160B jne casout ; skip case conversion if switched off 202 6B54 D341 movb r1,r13 ; get the character in a spare register 203 6B56 098D srl r13,8 ; move to low byte 204 6B58 028D ci r13,'a' ; compare to a 204 6B5A 0061 205 6B5C 1106 jlt casout ; if less than it's not a lower case char 206 6B5E 028D ci r13,'z' ; else compare to z 206 6B60 007A 207 6B62 1503 jgt casout ; if greater than it's not a lower case char 208 6B64 020D li r13,-32*256 ; it's lower case. load -32 in the upper byte 208 6B66 E000 209 6B68 B04D ab r13,r1 ; subtract -32 from the upper byte. 210 ; char is now upper case 211 6B6A 045B casout rt 212 ;] 213 214 ;[ NUMBER ( address length -- number flag ) 215 ; Attempts to convert the string at address into a number. If fully successful, 216 ; the number is placed on the stack and flag will be 0. If it fails (for example 217 ; contains an illegal character) then a partial number will be placed on the 218 ; stack (the value computed up until the failure) and flag will be >0. 219 ; Thus, if flag>0 the string failed to parse fully as a number. 220 ; A minus sign is permitted for negative numbers. 221 ; This routine uses BASE to parse numbers in the current BASE. 222 ; Eg. If BASE=16 then digits 0-9 and A-F are considered legal and will be 223 ; parsed properly. 224 ; A facility also exists called 'quick hex' that allows a number to be entered 225 ; in base 16, by placing a $ symbol at the end of the string. This avoids the 226 ; need to change BASE to enter a number. E.g. instead of HEX FEED DECIMAL you 227 ; can simply do $FEED. The number will be parsed as a HEX number without the 228 ; need to change BASE. 229 ; The numbers returned are (by default) singles (16 bits). NUMBER can can also 230 ; return a double (32-bit (2 stack cells)) value by including a period in the 231 ; number string. E.g. 100. 1.00 10.0 .100 will all return 100 decimal as a 232 ; double. 233 ; The various facilities can be mixed. For example, f. means -15 as a double. 234 ; - $ and . can be specified in any order. However, $ if required, should be 235 ; specified before any number digits. - and . can come anywhere in the string. 236 ; in the number string. 237 6B6C 6AD0 numbrh data findh,6 237 6B6E 0006 238 6B70 4E55 text 'NUMBER' 238 6B72 4D42 238 6B74 4552 239 6B76 8320 number data docol,lit,numvec,fetch,execut,exit ; fetch NUMBER vector & execute 239 6B78 70B2 239 6B7A A004 239 6B7C 6830 239 6B7E 72AA 239 6B80 832C 240 6B82 6B84 numbr1 data $+2 241 6B84 06A0 bl @bank1 241 6B86 8332 242 6B88 6BBA data _numbr ; see 1-08-Parsing.a99 243 ;] 244 245 ;[ EVALUATE ( i*x c-addr u -- j*x) 246 ; evaluates the string specified by c-addr u 247 ; the interpretation state is stored before evaluation and restored afterwards 248 ; should not be directly called within a block (or when BLK>0) 249 6B8A 6B6C evalh data numbrh,8 249 6B8C 0008 250 6B8E 4556 text 'EVALUATE' 250 6B90 414C 250 6B92 5541 250 6B94 5445 251 6B96 8320 eval data docol 252 6B98 770C data in_,fetch,rspush 252 6B9A 6830 252 6B9C 6290 253 6B9E 7B4E data blk,fetch,rspush 253 6BA0 6830 253 6BA2 6290 254 6BA4 7658 data span,fetch,rspush 254 6BA6 6830 254 6BA8 6290 255 6BAA 773E data tib_,fetch,rspush 255 6BAC 6830 255 6BAE 6290 256 257 6BB0 770C data in_,store0 ; zero >IN 257 6BB2 6892 258 6BB4 7B4E data blk,store0 ; zero BLK 258 6BB6 6892 259 6BB8 7658 data span,store ; load #tib with u 259 6BBA 6852 260 6BBC 773E data tib_,store ; load tib with c-addr 260 6BBE 6852 261 262 6BC0 609C data litm1,lit,source,store ; set SOURCE-ID to -1 262 6BC2 70B2 262 6BC4 A058 262 6BC6 6852 263 6BC8 72FE data interp ; call interpreter 264 6BCA 70B2 data lit,source,store0 ; zero SOURCE-ID 264 6BCC A058 264 6BCE 6892 265 266 6BD0 62AC data rspop,tib_,store 266 6BD2 773E 266 6BD4 6852 267 6BD6 62AC data rspop,span,store 267 6BD8 7658 267 6BDA 6852 268 6BDC 62AC data rspop,blk,store 268 6BDE 7B4E 268 6BE0 6852 269 6BE2 62AC data rspop,in_,store 269 6BE4 770C 269 6BE6 6852 270 6BE8 832C data exit 271 ;] 272 273 ;[ >CFA ( dictionary_address -- code_field_address) 274 ; Given a dictionary address returns the code-field address (CFA) of the word 275 6BEA 6B8A cfah data evalh,4 275 6BEC 0004 276 6BEE 3E43 text '>CFA' 276 6BF0 4641 277 6BF2 6BF4 cfa data $+2 278 6BF4 C094 _cfa mov *stack,r2 ; dictionary address 279 6BF6 C062 mov @2(r2),r1 ; word length 279 6BF8 0002 280 6BFA 0581 inc r1 ; round word length up to even number if odd 281 6BFC 0241 andi r1,>000e ; keep only rounded up length value 281 6BFE 000E 282 6C00 A042 a r2,r1 ; add length to dictionary address 283 6C02 8C71 c *r1+,*r1+ ; adjust by two words, one word for header 284 ; word, one word for length word. 285 ; we're now pointing at the CFA. nice trick 286 ; to add 4 to a register in only 2 bytes! 287 6C04 C501 mov r1,*stack ; move to stack 288 6C06 045C b *next ; NEXT 289 ;] 290 291 ;[ >BODY ( cfa -- body_address ) 292 ; Given a CFA, returns the address of the body (the address of the "payload") 293 ; of words created with CREATE. E.g. VARIABLE, VALUE, CONSTANT 294 6C08 6BEA tbodyh data cfah,5 294 6C0A 0005 295 6C0C 3E42 text '>BODY ' 295 6C0E 4F44 295 6C10 5920 296 6C12 839A tobody data _plus2 ; execute 2+ (see 0-03-Math.a99) 297 ;] 298 299 ;[ >LINK ( cfa -- link_field_address ) 300 ; given a code field address, returns the address of the beginning of the dictionary 301 ; entry (the address of the link field). 302 6C14 6C08 dfah data tbodyh 303 6C16 0005 data 5 304 6C18 3E4C text '>LINK ' 304 6C1A 494E 304 6C1C 4B20 305 6C1E 6C20 dfa data $+2 306 6C20 C020 mov @latest,r0 ; get latest dictionary entry 306 6C22 A044 307 6C24 C040 dfa1 mov r0,r1 ; copy it 308 6C26 05C0 inct r0 ; point to length 309 6C28 C090 mov *r0,r2 ; get the length 310 6C2A 0640 dect r0 ; point to beginning of dict entry again 311 6C2C 0242 andi r2,>f ; mask out immediate, hidden, and block 311 6C2E 000F 312 ; number, leaving length 313 6C30 A042 a r2,r1 ; add length 314 6C32 0581 inc r1 ; round up to... 315 6C34 0241 andi r1,>fffe ; ...word address 315 6C36 FFFE 316 6C38 05C1 inct r1 ; account for the length word itself 317 6C3A 05C1 inct r1 318 6C3C 8501 c r1,*stack ; is it what we're looking for? 319 6C3E 1303 jeq dfafnd ; jump if yes 320 6C40 C010 mov *r0,r0 ; otherwise walk the list 321 6C42 1301 jeq dfafnd ; if zero, we didn't find - push zero 322 6C44 10EF jmp dfa1 ; otherwise check the next entry in the list 323 6C46 C500 dfafnd mov r0,*stack ; place on stack 324 6C48 045C b *next 325 ;] * * COPY 'C:\TI\Source\TurboForth\Bank0\0-09-Console.a99' * 1 ; _____ _ __ __ _ 2 ; / ____| | | \ \ / / | | 3 ; | | ___ _ __ ___ ___ | | ___ \ \ /\ / /___ _ __ __| |___ 4 ; | | / _ \| '_ \/ __|/ _ \| |/ _ \ \ \/ \/ // _ \| '__/ _` / __| 5 ; | |____| (_) | | | \__ \ (_) | | __/ \ /\ /| (_) | | | (_| \__ \ 6 ; \_____|\___/|_| |_|___/\___/|_|\___| \/ \/ \___/|_| \__,_|___/ 7 ; Console IO words 8 9 ;[ BREAK? ( -- ) 10 ; scans keyboard and does an ABORT if break (FCTN 4) is pressed 11 6C4A 6C14 breakh data dfah,6 11 6C4C 0006 12 6C4E 4252 text 'BREAK?' 12 6C50 4541 12 6C52 4B3F 13 6C54 8320 break data docol,keyq,lit,2,eq,zbrnch,break1 13 6C56 6E62 13 6C58 70B2 13 6C5A 0002 13 6C5C 647A 13 6C5E 65F6 13 6C60 6C6E 14 6C62 6E92 data cr,toterm,brkmsg,5,cr,ab0rt 14 6C64 60B6 14 6C66 6C70 14 6C68 0005 14 6C6A 6E92 14 6C6C 7464 15 6C6E 832C break1 data exit 16 6C70 4272 brkmsg text 'Break ' 16 6C72 6561 16 6C74 6B20 17 ;] 18 19 ;[ GOTOXY ( x y -- ) 20 ; sets the screen cursor to the specified (0 based) x y screen coordinates 21 6C76 6C4A goxyh data breakh,6 21 6C78 0006 22 6C7A 474F text 'GOTOXY' 22 6C7C 544F 22 6C7E 5859 23 6C80 6C82 gotoxy data $+2 24 6C82 C834 mov *stack+,@scry ; pop y 24 6C84 A02A 25 6C86 C834 mov *stack+,@scrx ; pop x 25 6C88 A028 26 6C8A 045C b *next 27 ;] 28 29 ;[ TYPE addr +n -- M,79 30 ; +n characters are displayed from memory beginning with the character at addr 31 ; and continuing through consecutive addresses. 32 ; Nothing is displayed if +n is zero. 33 ; See: "9.5.4 TYPE" 34 6C8C 6C76 typeh data goxyh,4 34 6C8E 0004 35 6C90 5459 text 'TYPE' 35 6C92 5045 36 6C94 6C96 type data $+2 37 6C96 C374 type1 mov *stack+,r13 ; pop length in r13 38 6C98 C2B4 mov *stack+,r10 ; address in r10 39 6C9A C34D mov r13,r13 ; check the length 40 6C9C 120B jle typout ; if 0 or negative then exit 41 6C9E C020 mov @_wwrap,r0 ; check word-wrap 41 6CA0 A00A 42 6CA2 1609 jne dowwrap ; if <>0 then do word-wrap 43 44 6CA4 D1FA typlp movb *r10+,r7 ; get byte from string in r7 MSB 45 6CA6 06C7 swpb r7 ; rotate MSB into LSB 46 6CA8 0644 dect stack ; create space on stack 47 6CAA C507 mov r7,*stack ; place on stack 48 6CAC 06A0 bl @emit_ ; call emit 48 6CAE 6DA0 49 6CB0 060D dec r13 ; have we finished? 50 6CB2 16F8 jne typlp ; if not, repeat 51 6CB4 045C typout b *next 52 53 ; apply word-wrap behaviour 54 6CB6 10F6 dowwrap jmp typlp 55 ;] 56 57 ;[ WORDS ( -- ) 58 ; displays a list of all the words in the dictionary 59 6CB8 6C8C wordsh data typeh,5 59 6CBA 0005 60 6CBC 574F text 'WORDS ' 60 6CBE 5244 60 6CC0 5320 61 6CC2 8320 words_ data docol 62 6CC4 6E92 data cr,lit0,lates_ 62 6CC6 6084 62 6CC8 76DE 63 6CCA 6830 words1 data fetch,dup,zbrnch,words2 63 6CCC 6186 63 6CCE 65F6 63 6CD0 6D02 64 6CD2 6186 data dup,plus2,dup,fetch,lit,15,and 64 6CD4 62CE 64 6CD6 6186 64 6CD8 6830 64 6CDA 70B2 64 6CDC 000F 64 6CDE 67D2 65 6CE0 617C data swap,plus2,swap,type 65 6CE2 62CE 65 6CE4 617C 65 6CE6 6C94 66 6CE8 6C54 words3 data break 67 6CEA 6E62 words4 data keyq,lit,>ffff,eq,zbrnch,words4 67 6CEC 70B2 67 6CEE FFFF 67 6CF0 647A 67 6CF2 65F6 67 6CF4 6CEA 68 6CF6 6D38 data space1,swap,plus1,swap 68 6CF8 617C 68 6CFA 62BA 68 6CFC 617C 69 6CFE 65E4 data branch,words1 69 6D00 6CCA 70 6D02 6172 words2 data drop,cr,dot 70 6D04 6E92 70 6D06 783C 71 6D08 60B6 data toterm,wftxt,6 71 6D0A 6D10 71 6D0C 0006 72 6D0E 832C data exit 73 6D10 576F wftxt text 'Words ' 73 6D12 7264 73 6D14 7320 74 ;] 75 76 ;[ XY? ( -- x y ) 77 ; places the cursor x and y coordinates on the stack 78 6D16 6CB8 xyh data wordsh,3 78 6D18 0003 79 6D1A 5859 text 'XY? ' 79 6D1C 3F20 80 6D1E 6D20 xy data $+2 81 6D20 0644 dect stack ; new stack entry 82 6D22 C520 mov @scrX,*stack ; push scrX to stack 82 6D24 A028 83 6D26 0644 dect stack ; new stack entry 84 6D28 C520 mov @scrY,*stack ; push scrY to stack 84 6D2A A02A 85 6D2C 045C b *next 86 ;] 87 88 ;[ SPACE -- M,79 89 ; Displays an ASCII space. 90 6D2E 6D16 spaceh data xyh,5 90 6D30 0005 91 6D32 5350 text 'SPACE ' 91 6D34 4143 91 6D36 4520 92 6D38 6D3A space1 data $+2 93 6D3A 0644 dect stack ; new stack entry 94 6D3C 0200 li r0,32 ; space character 94 6D3E 0020 95 6D40 C500 mov r0,*stack ; push it to stack 96 6D42 06A0 bl @emit_ ; call emit 96 6D44 6DA0 97 6D46 045C b *next 98 ;] 99 100 ;[ SPACES +n -- M,79 101 ; Displays +n ASCII spaces. Nothing is displayed if +n is zero. 102 6D48 6D2E spcesh data spaceh,6 102 6D4A 0006 103 6D4C 5350 text 'SPACES' 103 6D4E 4143 103 6D50 4553 104 6D52 6D54 spces data $+2 105 6D54 C1F4 mov *stack+,r7 ; pop count in r7 106 6D56 C1C7 mov r7,r7 ; check for 0 107 6D58 1309 jeq spcesx ; if zero, just quit 108 6D5A 0747 abs r7 ; make positive if negative 109 6D5C 0644 spces1 dect stack ; create stack entry 110 6D5E 0208 li r8,32 ; space character 110 6D60 0020 111 6D62 C508 mov r8,*stack ; put space on stack 112 6D64 06A0 bl @emit_ ; display the space via emit 112 6D66 6DA0 113 6D68 0607 dec r7 ; decrement count 114 6D6A 16F8 jne spces1 ; repeat if not finished 115 6D6C 045C spcesx b *next 116 ;] 117 118 ;[ PAGE ( -- ) 119 ; clears screen 120 6D6E 6D48 clsh data spcesh,4 120 6D70 0004 121 6D72 5041 text 'PAGE' 121 6D74 4745 122 6D76 6D78 cls data $+2 123 6D78 06A0 bl @bank1 123 6D7A 8332 124 6D7C 6132 data _cls ; see 1-02-Console.a99 125 ;] 126 127 ;[ JOYST ( joystick# -- value ) 128 ; Scans the joystick returning the direction value 129 6D7E 6D6E joysth data clsh,5 129 6D80 0005 130 6D82 4A4F text 'JOYST ' 130 6D84 5953 130 6D86 5420 131 6D88 6D8A joyst data $+2 132 6D8A 06A0 bl @bank1 ; see 1-02-Console.a99 132 6D8C 8332 133 6D8E 615A data _joyst 134 ;] 135 136 ;[ EMIT 16b -- M,83 137 ; The least-significant 8-bit ASCII character is displayed. SEE: "9.5.3 EMIT" 138 6D90 6D7E emith data joysth,4 138 6D92 0004 139 6D94 454D text 'EMIT' 139 6D96 4954 140 6D98 6D9A emit data $+2 141 ; EMIT as called from the Forth environment: 142 6D9A 06A0 bl @emit_ ; call emit routine (see below) 142 6D9C 6DA0 143 6D9E 045C b *next 144 145 ; emit as an internal assembly sub-routine (used by SPACE, SPACES & TYPE): 146 6DA0 C24B emit_ mov r11,r9 ; save return address 147 6DA2 06A0 bl @ccp ; compute cursor position (loaded into r0) 147 6DA4 6F14 148 6DA6 C074 mov *stack+,r1 ; pop character 149 6DA8 06C1 swpb r1 ; get byte in msb 150 6DAA 06A0 bl @vsbw ; write char to screen at computed position 150 6DAC 7F9A 151 6DAE 05A0 inc @scrX ; increment x postion of cursor 151 6DB0 A028 152 6DB2 8820 c @scrx,@xmax ; have we hit the right-most column? 152 6DB4 A028 152 6DB6 A02C 153 6DB8 1301 jeq clipx ; if yes, reset x 154 6DBA 0459 b *r9 ; else return 155 6DBC 04E0 clipx clr @scrX ; reset x to 0 155 6DBE A028 156 6DC0 05A0 inc @scrY ; increment y 156 6DC2 A02A 157 6DC4 8820 c @scrY,@ymax ; have we hit the bottom of the screen? 157 6DC6 A02A 157 6DC8 A02E 158 6DCA 136F jeq scrlup ; if yes then scroll screen up 159 6DCC 0459 b *r9 ; else return 160 ;] 161 162 ;[ KEY -- 16b M,83 163 ; The least-significant 7 bits of 16b is the next ASCII character received. 164 ; All valid ASCII characters can be received. 165 ; Control characters are not processed by the system for any editing purpose. 166 ; Characters received by KEY will not be displayed. 167 ; See: "9.5.1 KEY" 168 0000 FF00 nokey equ >ff00 ; keycode for no key pressed 169 0000 0003 delkey equ 3 ; keycode for delete key 170 171 6DCE 6D90 kscnh data emith,3 171 6DD0 0003 172 6DD2 4B45 text 'KEY ' 172 6DD4 5920 173 6DD6 6DD8 key data $+2 174 6DD8 04E0 clr @cursrd 174 6DDA A024 175 6DDC 06A0 bl @kscn ; call key scan routine 175 6DDE 6DE2 176 6DE0 045C b *next ; NEXT 177 ; keyscan has been split from the forth word KEY. 178 ; this allows it to be called both as a forth word (KEY) and as a machine 179 ; code routine. 180 6DE2 C20B kscn mov r11,r8 ; save return address 181 6DE4 06A0 kscn1 bl @cflash ; call cursor flash routine 181 6DE6 6E22 182 6DE8 D820 movb @keydev,@>8374 ; set keyboard to scan 182 6DEA A022 182 6DEC 8374 183 6DEE 02E0 lwpi >83e0 ; use gpl workspace 183 6DF0 83E0 184 6DF2 06A0 bl @>000e ; call keyboard scanning routine 184 6DF4 000E 185 ; restore the turboforth workspace 186 ; TFs workspace is held in 'wp'. This routine writes a program in the GPL 187 ; workspace starting at R0 which performs an LWPI instruction, and then 188 ; jumps the remainder of this keyscan routine below. 189 ; 190 6DF6 0200 li r0,>02e0 ; lwpi instruction 190 6DF8 02E0 191 6DFA C060 mov @wp,r1 ; lwpi operand 191 6DFC A012 192 6DFE 0202 li r2,>0460 ; branch opcode 192 6E00 0460 193 6E02 0203 li r3,kscn2 ; operand for branch instruction 193 6E04 6E08 194 6E06 0440 b r0 195 6E08 D1E0 kscn2 movb @gplst,r7 ; get GPL STATUS byte in r7 MSB 195 6E0A 837C 196 6E0C 0A37 sla r7,3 ; shift COND bit into carry bit 197 6E0E 17EA jnc kscn1 ; no key pressed, or same key pressed as 198 ; previous scan. ignore and re-scan. 199 6E10 D1E0 movb @keyin,r7 ; a new key was pressed: get ascii code in 199 6E12 8375 200 ; r7 msb 201 6E14 0287 ci r7,nokey ; compare against 'no key pressed' code 201 6E16 FF00 202 6E18 13E5 jeq kscn1 ; no key was pressed 203 6E1A 0987 srl r7,8 ; a key was pressed. move to low byte 204 6E1C 0644 dect stack ; new stack entry 205 6E1E C507 mov r7,*stack ; place ascii code onto stack 206 6E20 0458 b *r8 ; return to caller 207 208 ; cursor flashing 209 6E22 C820 cflash mov @bank0,@retbnk ; return to bank 0 209 6E24 606A 209 6E26 A06E 210 6E28 0300 limi 2 ; service isr 210 6E2A 0002 211 6E2C 0300 limi 0 211 6E2E 0000 212 6E30 C18B mov r11,r6 ; save return address 213 6E32 0207 li r7,>2000 ; load space & ascii 0 characters for cursor 213 6E34 2000 214 6E36 C020 mov @cursrd,r0 ; get cursor delay 214 6E38 A024 215 6E3A 0220 ai r0,>80 ; increment 215 6E3C 0080 216 6E3E C800 mov r0,@cursrd ; save it 216 6E40 A024 217 6E42 1305 jeq csrwrt ; if zero, write a blank cursor character 218 6E44 06C7 swpb r7 ; load _ cursor character 219 6E46 0280 ci r0,>8000 ; cursror delay = >8000? 219 6E48 8000 220 6E4A 1301 jeq csrwrt ; if yes, write an _ cursor character 221 6E4C 0456 b *r6 ; if neither, just return 222 6E4E 06A0 csrwrt bl @ccp ; call compute cursor position 222 6E50 6F14 223 6E52 C047 mov r7,r1 ; move cursor character to r1 for VSBW 224 6E54 06A0 bl @vsbw ; write the cursror character to the screen 224 6E56 7F9A 225 6E58 0456 b *r6 ; return to caller 226 ;] 227 228 ;[ KEY? ( -- ascii/-1 ) 229 ; Scans keyboard and returns the ascii code of the key pressed, 230 ; or -1 if no key pressed 231 6E5A 6DCE keyqh data kscnh,4 231 6E5C 0004 232 6E5E 4B45 text 'KEY?' 232 6E60 593F 233 6E62 6E64 keyq data $+2 234 6E64 06A0 bl @keyqsr ; call as subroutine 234 6E66 6E6A 235 6E68 045C b *next 236 6E6A D820 keyqsr movb @keydev,@>8374 ; set keyboard to scan 236 6E6C A022 236 6E6E 8374 237 6E70 02E0 lwpi >83e0 ; use gpl workspace 237 6E72 83E0 238 6E74 06A0 bl @>000e ; call keyboard scanning routine 238 6E76 000E 239 6E78 02E0 lwpi wkspc ; restore to our workspace 239 6E7A 8300 240 6E7C D1E0 movb @keyin,r7 ; a new key was pressed: get ascii code in r7 msb 240 6E7E 8375 241 6E80 0887 sra r7,8 ; move to low byte 242 6E82 0644 dect stack ; make space on stack 243 6E84 C507 mov r7,*stack ; place value on stack 244 6E86 C80C mov r12,@>83d6 ; defeat auto screen blanking 244 6E88 83D6 245 6E8A 045B rt ; return to caller 246 ;] 247 248 ;[ CR -- M,79 "c-r" 249 ; Displays a carriage-return and line-feed or equivalent operation. 250 6E8C 6E5A crh data keyqh,2 250 6E8E 0002 251 6E90 4352 text 'CR' 252 6E92 6E94 cr data $+2 253 6E94 0209 li r9,crexit ; return address if we take the jump to scrlup 253 6E96 6EA8 254 6E98 04E0 clr @scrx ; clear cursor x coordinate 254 6E9A A028 255 6E9C 05A0 inc @scry ; move to next screen row 255 6E9E A02A 256 6EA0 8820 c @scry,@ymax ; have we hit the bottom of the screen? 256 6EA2 A02A 256 6EA4 A02E 257 6EA6 1301 jeq scrlup ; if yes, then scroll the screen 258 ; scrlup will return here via r9 259 6EA8 045C crexit b *next ; NEXT 260 ;] 261 262 ; Scroll screen up by one line. Used by EMIT and CR to scroll the screen up if 263 ; necessary (sub-routine, not a FORTH word). 264 6EAA C220 scrlup mov @noscrl,r8 ; test NOSCROLL 264 6EAC A026 265 6EAE 132D jeq scrlno ; scrolling is supressed 266 6EB0 0620 dec @scrY ; clip y coordinate to 23 266 6EB2 A02A 267 6EB4 C220 mov @here,r8 267 6EB6 A046 268 6EB8 0206 li r6,23 ; 23 lines to shift 268 6EBA 0017 269 6EBC 04C0 clr r0 ; screen address 270 6EBE A020 sclup_ a @xmax,r0 ; move down one line 270 6EC0 A02C 271 6EC2 C048 mov r8,r1 ; address of buffer to store in 272 6EC4 C0A0 mov @xmax,r2 ; number of bytes to store in the screen 272 6EC6 A02C 273 ; line buffer 274 6EC8 06A0 bl @vmbr ; read screen data into buffer 274 6ECA 7F82 275 6ECC 0520 neg @xmax ; set x negative 275 6ECE A02C 276 6ED0 A020 a @xmax,r0 ; move up one line 276 6ED2 A02C 277 6ED4 0520 neg @xmax ; restore x to positive 277 6ED6 A02C 278 6ED8 C0A0 mov @xmax,r2 ; number of bytes to write 278 6EDA A02C 279 6EDC C048 mov r8,r1 ; address of screen buffer 280 6EDE 06A0 bl @vmbw ; write buffer to screen 280 6EE0 7FC2 281 6EE2 A020 a @xmax,r0 ; move down a line 281 6EE4 A02C 282 6EE6 0606 dec r6 ; decrement number of lines left to shift 283 6EE8 16EA jne sclup_ ; repeat if not finished 284 6EEA C0A0 mov @here,r2 284 6EEC A046 285 6EEE C1A0 mov @xmax,r6 ; screen width 285 6EF0 A02C 286 6EF2 0201 li r1,>2020 ; two space characters 286 6EF4 2020 287 6EF6 CC81 blnkln mov r1,*r2+ ; write two spaces to the buffer 288 6EF8 0646 dect r6 ; decrement character count 289 6EFA 16FD jne blnkln ; loop if not finished 290 6EFC C060 mov @here,r1 290 6EFE A046 291 6F00 C0A0 mov @xmax,r2 ; number of bytes to write in r2 291 6F02 A02C 292 6F04 06A0 bl @vmbw ; write blank line 292 6F06 7FC2 293 6F08 0459 b *r9 ; return 294 6F0A 04E0 scrlno clr @scrY ; scrolling is supressed, so zero Y 294 6F0C A02A 295 6F0E 04E0 clr @scrX ; and x 295 6F10 A028 296 6F12 0459 b *r9 ; and return 297 298 ; compute cursor position. common utility routine. 299 ; used by EMIT and the cursor flash routine in KEY 300 6F14 C020 ccp mov @scry,r0 ; y coordinate of screen in r0 300 6F16 A02A 301 6F18 C060 mov @xmax,r1 ; horizontal screen size in r1 301 6F1A A02C 302 6F1C 3840 mpy r0,r1 ; multiply y by horizontal screen size. 303 ; result in r2 304 6F1E C002 mov r2,r0 ; move to r0 for vdp access routines 305 6F20 A020 a @scrX,r0 ; add x coordinate 305 6F22 A028 306 6F24 045B rt 307 308 ;[ BYE ( -- ) 309 ; resets the console back to the title screen 310 6F26 6E8C byeh data crh,3 310 6F28 0003 311 6F2A 4259 text 'BYE ' 311 6F2C 4520 312 6F2E 6F30 bye data $+2 313 6F30 04E0 clr @isr ; remove isr hook 313 6F32 83C4 314 6F34 0420 blwp @0 ; cold reset console. So long, old pal. 314 6F36 0000 315 ;] * * COPY 'C:\TI\Source\TurboForth\Bank0\0-10-Compilation.a99' * 1 ; _____ _ _ _ __ __ _ 2 ; / ____| (_) (_) \ \ / / | | 3 ; | | ___ _ __ ___ _ __ _| |_ _ __ __ _ \ \ /\ / /___ _ __ __| |___ 4 ; | | / _ \| '_ ` _ \| '_ \| | | | '_ \ / _` | \ \/ \/ // _ \| '__/ _` / __| 5 ; | |____| (_) | | | | | | |_) | | | | | | | (_| | \ /\ /| (_) | | | (_| \__ \ 6 ; \_____|\___/|_| |_| |_| .__/|_|_|_|_| |_|\__, | \/ \/ \___/|_| \__,_|___/ 7 ; | | __/ | 8 ; |_| |___/ 9 ; Compilation words... 10 11 ;[ HEADER ( TIB:string -- ) 12 ; creates a word (from the input source) in the dictionary and links the 13 ; dictionary 14 ; ********************************************************************* 15 ; NOTE: FOR VERSIONS 1.2.1 ONWARDS: 16 ; HEADER NOW DOES A "BL WORD" SEQUENCE INTERNALLY. 17 ; NO NEED TO DO A "BL WORD HEADER" SEQUENCE IN CODE THAT USES HEADER. 18 ; HEADER NOW DOES IT FOR YOU. 19 ; ********************************************************************* 20 6F38 6F26 headrh data byeh,6 20 6F3A 0006 21 6F3C 4845 text 'HEADER' 21 6F3E 4144 21 6F40 4552 22 6F42 8320 header data docol 23 6F44 70EC data align ; ensure HERE is aligned 24 6F46 72B2 data spword ; get a word from the input source 25 6F48 6F4C data headr ; create and link new dictionary entry 26 6F4A 832C data exit 27 6F4C 6F4E headr data $+2 28 6F4E 06A0 bl @bank1 28 6F50 8332 29 6F52 6C92 data _headr ; see 1-09-Compilation.a99 30 ;] 31 32 ;[ MARKER ( -- ) 33 ; creates a marker in the dictionary that, when executed, removes all words 34 ; following the marker from the dictionary, and resets the compilation address 35 ; to the first free address following the marker. 36 ; Example: 37 ; MARKER RESET \ create a marker called reset 38 ; : test1 1 2 3 ; \ define some words 39 ; : test2 4 5 6 ; 40 ; : test3 7 8 9 ; 41 ; RESET 42 ; In the example above, upon execution of RESET, the words test1 test2 & test3 43 ; are removed from the dictionary, LATEST points to the link field of RESET and 44 ; H points to the next cell after the end of the definition of RESET. 45 ; FFAIHM & FFAILM are also updated. 46 6F54 6F38 markrh data headrh,6 46 6F56 0006 47 6F58 4D41 text 'MARKER' 47 6F5A 524B 47 6F5C 4552 48 6F5E 8320 markr data docol 49 6F60 6F42 data header 50 6F62 7262 data compile,docol 50 6F64 8320 51 6F66 7262 data compile,domark 51 6F68 6F84 52 6F6A 76DE data lates_,fetch,comma 52 6F6C 6830 52 6F6E 70CC 53 6F70 780E data ghere,lit,6,add,comma 53 6F72 70B2 53 6F74 0006 53 6F76 631E 53 6F78 70CC 54 ; branch to code in FORGET to force update of FFAILM & FFAIHM... 55 ; data compile,branch,lit,forg1,comma 56 6F7A 7262 data compile,align 56 6F7C 70EC 57 6F7E 7262 DATA COMPILE,EXIT 57 6F80 832C 58 6F82 832C data exit 59 6F84 6F86 domark data $+2 60 6F86 C833 mov *pc+,@latest 60 6F88 A044 61 6F8A C833 mov *pc+,@here 61 6F8C A046 62 6F8E 045C b *next 63 ;] 64 65 ;[ CREATE -- M,79 66 ; A defining word executed in the form: 67 ; CREATE 68 ; Creates a dictionary entry for . After 69 ; available dictionary location is the first byte ofis created, the next 's parameter field. 70 ; Whenis subsequently executed, the address of the first byte of 71 ;'s parameter field is left on the stack. 72 ; CREATE does not allocate space in's parameter field. 73 6F90 6F54 creath data markrh,6 73 6F92 0006 74 6F94 4352 text 'CREATE' 74 6F96 4541 74 6F98 5445 75 6F9A 8320 create data docol 76 6F9C 6F42 data header ; create and link dictionary entry 77 6F9E 7262 data compile,crtime ; compile create's run-time to CREATEd CFA 77 6FA0 6FA4 78 6FA2 832C data exit 79 80 ; the run-time behaviour of all words created with CREATE is to leave their PFA 81 ; on the stack... Children of CREATE invoke the following code, called by the 82 ; inner interpreter: 83 6FA4 0644 crtime dect stack ; make room for PFA 84 6FA6 C506 mov r6,*stack ; place PFA on stack 85 6FA8 045C b *next 86 ;] 87 88 ;[ patches CFA of last created word with address of run-time code of parent. 89 ; address contained in PATCH. Used by DOES> 90 6FAA 6FAC altcfa data $+2 91 6FAC C020 mov @patch,r0 ; CFA of most recent definition 91 6FAE A06A 92 6FB0 C403 mov pc,*r0 ; patch it with parent's code field 93 6FB2 C0F5 mov *rstack+,pc ; in-line EXIT that "ends" the definition 94 6FB4 045C b *next ; into which altcfa is compiled 95 ;] 96 97 ;[ DODOES 98 ; dynamically compiles instructions (for run-time transition from child to 99 ; parent for DOES> words) into the parent DOES> word. 100 6FB6 8320 dodoes data docol 101 6FB8 7262 data compile,>0644 ; compile: "dect stack" instruction 101 6FBA 0644 102 6FBC 7262 data compile,>C506 ; compile: "mov r6,*stack" instruction 102 6FBE C506 103 6FC0 7262 data compile,>0645 ; compile: "dect rstack" instruction 103 6FC2 0645 104 6FC4 7262 data compile,>C543 ; compile: "mov pc,*rstack" instruction 104 6FC6 C543 105 6FC8 7262 data compile,>0203 ; compile: "li pc,xxx" instruction 105 6FCA 0203 106 ; calculate & compile address of xxx for li instruction: 107 6FCC 780E data ghere,lit,4,add,comma 107 6FCE 70B2 107 6FD0 0004 107 6FD2 631E 107 6FD4 70CC 108 6FD6 7262 data compile,>045C ; compile "b *next" instruction 108 6FD8 045C 109 6FDA 832C data exit 110 ;] 111 112 ;[ DOES> -- addr C,I,83 "does" 113 ; -- (compiling) 114 ; Defines the execution-time action of a word created by a high-level defining 115 ; word. 116 ; Used in the form: 117 ; :... ; 118 ; and then 119 ;... DOES> ... 120 ; where is CREATE or any user defined word which executes CREATE. 121 ; 122 ; Marks the termination of the defining part of the defining wordand 123 ; then begins the definition of the execution-time action for words that will 124 ; later be defined by. When 125 ;is later executed, the address of 's parameter field is placed on the stack and then the sequence of words 126 ; between DOES> and ; are executed. 127 6FDC 6F90 doesh data creath,immed+5 127 6FDE 8005 128 6FE0 444F text 'DOES> ' 128 6FE2 4553 128 6FE4 3E20 129 6FE6 8320 does data docol,compile,altcfa,dodoes,exit 129 6FE8 7262 129 6FEA 6FAA 129 6FEC 6FB6 129 6FEE 832C 130 ;] 131 132 ;[ CONSTANT 16b -- M,83 133 ; A defining word executed in the form: 134 ; 16b CONSTANT135 ; Creates a dictionary entry for so that when 136 ; 16b will be left on the stack. 137 6FF0 6FDC consth data doesh,8 137 6FF2 0008 138 6FF4 434F text 'CONSTANT' 138 6FF6 4E53 138 6FF8 5441 138 6FFA 4E54 139 6FFC 8320 const data docol 140 6FFE 6F42 data header ; create and link dictionary entry 141 7000 7262 data compile,docon ; compile reference to docon 141 7002 7008 142 7004 70CC data comma ; compile in the value of constant as an 143 ; argument to docon 144 7006 832C data exit 145 146 ; children of constant run this code... 147 7008 0644 docon dect stack ; make space on the data stack 148 700A C516 mov *r6,*stack ; push payload to the stack 149 700C 045C b *next 150 ;] 151 152 ;[ VARIABLE -- M,79 153 ; A defining word executed in the form: 154 ; VARIABLEis later executed, 155 ; A dictionary entry for is created and two bytes are ALLOTted in its 156 ; parameter field. 157 ; This parameter field is to be used for contents of the variable. 158 ; Whenis later executed, the address of its parameter field is placed 159 ; on the stack. 160 700E 6FF0 varh data consth,8 160 7010 0008 161 7012 5641 text 'VARIABLE' 161 7014 5249 161 7016 4142 161 7018 4C45 162 701A 8320 var data docol,create,lit0,comma,exit 162 701C 6F9A 162 701E 6084 162 7020 70CC 162 7022 832C 163 ;] 164 165 ;[ VALUE ( n -- ) 166 ; A "value" is actually a variable, but with more friendly syntax. VALUEs work 167 ; in conjunction with TO and +TO. (Perversely, they are implemented internally 168 ; using constants!) 169 ; A value can be initialised with a value at the time of creation: 170 ; 10 VALUE TEN - creates a word that pushes 10 to the stack when executed. 171 ; Note how the value was created and intialised at the same time. Using 172 ; standard variables, we would have to do: 173 ; VARIABLE TEN 10 TEN ! - two distinct steps. 174 ; To get the value of the value, just execute it: 175 ; 10 VALUE TEN TEN . 10 ok 176 ; Values, once created can have their values changed with the TO command: 177 ; 100 VALUE DELAY (creates a VALUE called delay with the value of 100) 178 ; 55 TO DELAY (changes the value of DELAY to 55) 179 ; Using standard variables, we would have to do: 180 ; VARIABLE DELAY 181 ; 100 DELAY ! 182 ; 55 DELAY ! 183 7024 700E valueh data varh,5 183 7026 0005 184 7028 5641 text 'VALUE ' 184 702A 4C55 184 702C 4520 185 702E 8320 value data docol,const,exit 185 7030 6FFC 185 7032 832C 186 ; no coolness here, it's just a constant, the coolness is in TO & +TO 187 ;] 188 189 ;[ TO ( n -- ) 190 ; Allows the value of an already created VALUE to be changed: 191 ; 100 VALUE SETPOINT (create a SETPOINT value with the value of 100) 192 ; 65 TO SETPOINT (change SETPOINTs value to 65) 193 7034 7024 toh data valueh,immed+2 193 7036 8002 194 7038 544F text 'TO' 195 703A 8320 data docol,toutil,zbrnch,tohx 195 703C 708C 195 703E 65F6 195 7040 704A 196 ; runs if in compile state. In compile state, a number will be on the 197 ; stack, so compile a reference to doto 198 7042 7262 data compile,doto ; compile reference to "do to" 198 7044 7056 199 7046 70CC data comma ; compile body address 200 7048 832C data exit 201 202 ; runs in interpret state - write the value on the stack to the body 203 ; address.... 204 704A 6852 tohx data store,exit 204 704C 832C 205 206 704E 7034 dotoh data toh,4 206 7050 0004 207 7052 2854 text '(TO)' 207 7054 4F29 208 7056 7058 doto data $+2 209 7058 C033 mov *pc+,r0 ; get in-line body address 210 705A C434 mov *stack+,*r0 ; move tos to values' body 211 705C 045C b *next 212 ;] 213 214 ;[ +TO ( n -- ) 215 ; Similar to TO above, but adds the value on the stack to the value. 216 ; 100 VALUE SETPOINT (create a value called SETPOINT with the value 100) 217 ; 25 +TO SETPOINT (changes SETPOINTs value to 125) 218 705E 704E addtoh data dotoh,immed+3 218 7060 8003 219 7062 2B54 text '+TO ' 219 7064 4F20 220 7066 8320 data docol,ToUtil,zbrnch,addtox 220 7068 708C 220 706A 65F6 220 706C 7076 221 ; runs if in compile state. In compile state, a number will be on the 222 ; stack, so compile a reference to dopto ("do plus-to") 223 706E 7262 data compile,dopto ; compile reference to "do plus-to" 223 7070 7084 224 7072 70CC data comma ; compile body address 225 7074 832C data exit 226 ; runs in interpret state - write the value on the stack to the body 227 ; address.... 228 7076 6860 addtox data stadd,exit 228 7078 832C 229 230 707A 705E ptoh data addtoh,5 230 707C 0005 231 707E 282B text '(+TO) ' 231 7080 544F 231 7082 2920 232 7084 7086 dopto data $+2 233 7086 C033 mov *pc+,r0 ; get in-line body address 234 7088 A434 a *stack+,*r0 ; pop and add tos to value in the values' body 235 708A 045C b *next 236 ;] 237 238 ; common routine to get body and state. Used by TO and +TO save a few bytes by 239 ; making it common, and no run time penalty since this bit of code executes at 240 ; compile time. 241 ; ( -- body state) 242 ToUtil ; data docol,spword,find,drop,tobody,state_,fetch,exit 243 708C 8320 data docol,getword,tobody,state_,fetch,exit 243 708E 72BA 243 7090 6C12 243 7092 76CC 243 7094 6830 243 7096 832C 244 245 ;[ ALLOT w -- 79 246 ; Allocates w bytes in the dictionary. 247 ; The address of the next available dictionary entry is updated accordingly. 248 7098 707A alloth data ptoh,5 248 709A 0005 249 709C 414C text 'ALLOT ' 249 709E 4C4F 249 70A0 5420 250 70A2 70A4 allot data $+2 251 70A4 06A0 bl @bank1 251 70A6 8332 252 70A8 6D2C data _allot ; see 1-09-Compilation.a99 253 ;] 254 255 ;[ LIT ( -- n ) 256 ; places the literal number on the datastack 257 70AA 7098 lith data alloth,3 257 70AC 0003 258 70AE 4C49 text 'LIT ' 258 70B0 5420 259 70B2 8368 lit data _lit ; runs from 16-bit ram 260 ;] 261 262 ;[ LITERAL -- 16b C,I,79 263 ; 16b -- (compiling) 264 ; Typically used in the form: 265 ; [ 16b ] LITERAL 266 ; Compiles a system dependent operation so that when later executed, 267 ; 16b will be left on the stack. 268 70B4 70AA literh data lith,immed+7 268 70B6 8007 269 70B8 4C49 text 'LITERAL ' 269 70BA 5445 269 70BC 5241 269 70BE 4C20 270 70C0 8320 litral data docol 271 70C2 60AC data clc ; compile lit and value from stack 272 70C4 832C data exit 273 ;] 274 275 ;[ , 16b -- 79 "comma" 276 ; ALLOT space for 16b then store 16b at HERE 2- . 277 70C6 70B4 commah data literh,1 277 70C8 0001 278 70CA 2C20 text ', ' 279 70CC 70CE comma data $+2 280 70CE 06A0 bl @bank1 280 70D0 8332 281 70D2 6CD0 data _comma ; see 1-09-Compilation.a99 282 ;] 283 284 ;[ C, (COMMA) ( value -- ) 285 ; appends an 8 bit value, from the least significant byte of TOS to HERE. 286 ; Here is incremented by ONE BYTE, not one WORD. 287 ; For safety, use ALIGN to align HERE to a word boundary afterwards. 288 70D4 70C6 ccommh data commah,2 288 70D6 0002 289 70D8 432C text 'C,' 290 70DA 70DC ccomma data $+2 291 70DC 06A0 bl @bank1 291 70DE 8332 292 70E0 6CEE data _comab ; see 1-09-Compilation.a99 293 ;] 294 295 ;[ ALIGN ( -- ) 296 ; Aligns HERE to an even word boundary by rounding up if required 297 ; Call it after using C! 298 70E2 70D4 alignh data ccommh,5 298 70E4 0005 299 70E6 414C text 'ALIGN ' 299 70E8 4947 299 70EA 4E20 300 70EC 70EE align data $+2 301 70EE 06A0 bl @bank1 301 70F0 8332 302 70F2 6CFE data _align ; see 1-09-Compilation.a99 303 ;] 304 305 ;[ [ -- I,79 "left-bracket" 306 ; -- (compiling) 307 ; Sets interpret state. 308 ; The text from the input stream is subsequently interpreted. 309 ; For typical usage see LITERAL . See: ] 310 70F4 70E2 lbrakh data alignh,immed+1 310 70F6 8001 311 70F8 5B20 text '[ ' 312 70FA 70FC lbrack data $+2 313 70FC 04E0 clr @_state ; set state to 0 313 70FE A048 314 7100 045C b *next 315 ;] 316 317 ;[ ] -- 79 "right-bracket" 318 ; Sets compilation state. 319 ; The text from the input stream is subsequently compiled. 320 ; For typical usage see LITERAL . See: [ 321 7102 70F4 rbrakh data lbrakh,1 321 7104 0001 322 7106 5D20 text '] ' 323 7108 710A rbrack data $+2 324 710A 0720 seto @_state ; set state to non zero 324 710C A048 325 710E 045C b *next 326 ;] 327 328 ;[ : -- sys M,79 "colon" 329 ; A defining word executed in the form: 330 ; :... ; 331 ; Create a word definition forin the compilation vocabulary and set 332 ; compilation state. 333 ; The search order is changed so that the first vocabulary in the search order 334 ; is changed so that the first vocabulary in the search order is replaced by the 335 ; compilation vocabulary. 336 ; The compilation vocabulary is unchanged. The text from the input stream is 337 ; subsequently compiled. 338 ;is called a "colon definition". 339 ; The newly created word definition forcannot be found in the dictionary 340 ; until the corresponding ; or ; ;CODE is successfully processed. 341 ; An error condition exists if a word is not found and cannot be converted to a 342 ; number or if, during compilation from mass storage, the input stream is 343 ; exhausted before encountering ; or ;CODE. 344 ; sys is balanced with its corresponding ; 345 ; See: "compilation" "9.4 Compilation" 346 7110 7102 colonh data rbrakh,1 346 7112 0001 347 7114 3A20 text ': ' 348 7116 8320 colon data docol 349 ; reset error detection reference counts.... 350 7118 70B2 data lit,ifcnt,lit,sal-ifcnt,lit0,fill 350 711A A07C 350 711C 70B2 350 711E 000C 350 7120 6084 350 7122 6970 351 ; begin compilation... 352 7124 770C data in_,fetch ; save >IN 352 7126 6830 353 7128 6F42 data header ; create entry and link dictionary 354 712A 76DE data lates_,fetch,hideme ; set *this* entry as hidden 354 712C 6830 354 712E 721C 355 7130 770C data in_,store ; restore >IN 355 7132 6852 356 7134 72B2 data spword,find ; see if word already exists. 356 7136 6AD8 357 ; FIND won't find *this* instance! 358 7138 70B2 data lit,temp,store,drop ; store result in temp. used later by ; 358 713A A070 358 713C 6852 358 713E 6172 359 7140 7262 data compile,docol ; compile DOCOL 359 7142 8320 360 7144 7108 data rbrack ; switch on compile mode 361 7146 832C data exit 362 363 ;] 364 365 ;[ CODE: ( -- ) 366 ; Defines a machine code word. 367 7148 7110 codeh data colonh,5 367 714A 0005 368 714C 434F text 'CODE: ' 368 714E 4445 368 7150 3A20 369 7152 8320 data docol 370 7154 6F42 data header 371 7156 780E data ghere,plus2,comma 371 7158 62CE 371 715A 70CC 372 715C 609C data litm1,lit,coding,store 372 715E 70B2 372 7160 A068 372 7162 6852 373 7164 832C data exit 374 ;] 375 376 ;[ ;CODE ( -- ) 377 ; ends a machine code definition 378 7166 7148 ecodeh data codeh,immed+5 378 7168 8005 379 716A 3B43 text ';CODE ' 379 716C 4F44 379 716E 4520 380 7170 8320 ecode data docol 381 7172 70B2 data lit,>045c,comma,lit,coding,store0 381 7174 045C 381 7176 70CC 381 7178 70B2 381 717A A068 381 717C 6892 382 717E 832C data exit 383 ;] 384 385 ;[ ; -- C,I,79 "semi-colon" 386 ; sys -- (compiling) 387 ; Stops compilation of a colon definition, allows theof this colon 388 ; definition to be found in the dictionary, sets interpret state and compiles 389 ; EXIT (or a system dependent word which performs an equivalent function). 390 ; sys is balanced with its corresponding : . 391 ; See: EXIT : "stack, return" "9.4 Compilation" 392 7180 7166 semih data ecodeh,immed+1 392 7182 8001 393 7184 3B20 text '; ' 394 7186 8320 semi data docol 395 7188 7262 data compile,exit ; compile EXIT 395 718A 832C 396 718C 76DE data lates_,fetch,hideme ; un-hide the word 396 718E 6830 396 7190 721C 397 398 ; flag to indicate no unbalanced errors detected... 399 7192 6084 data lit0 400 401 ; check IF...THEN reference counts, error if count>0... 402 7194 70B2 data lit,ifcnt,fetch,zbrnch,doerr 402 7196 A07C 402 7198 6830 402 719A 65F6 402 719C 71A6 403 719E 7204 data isserr 404 71A0 60B6 data toterm,iferr,7 404 71A2 7558 404 71A4 0007 405 406 ; check DO...LOOP reference counts, error if count>0... 407 71A6 70B2 doerr data lit,docnt,fetch,zbrnch,caserr 407 71A8 A07E 407 71AA 6830 407 71AC 65F6 407 71AE 71B8 408 71B0 7204 data isserr 409 71B2 60B6 data toterm,doertx,14 409 71B4 755F 409 71B6 000E 410 411 ; check CASE...ENDCASE reference counts, error if count>0 412 71B8 70B2 caserr data lit,cascnt,fetch,zbrnch,oferr 412 71BA A082 412 71BC 6830 412 71BE 65F6 412 71C0 71CA 413 71C2 7204 data isserr 414 71C4 60B6 data toterm,castxt,12 414 71C6 756D 414 71C8 000C 415 416 ; check OF...ENDOF reference counts, error if count>0 417 71CA 70B2 oferr data lit,ofcnt,fetch,zbrnch,begerr 417 71CC A084 417 71CE 6830 417 71D0 65F6 417 71D2 71DC 418 71D4 7204 data isserr 419 71D6 60B6 data toterm,oftxt,8 419 71D8 7579 419 71DA 0008 420 421 ; check BEGIN/UNTIL/REPEAT reference counts, error if count>0 422 71DC 70B2 begerr data lit,begcnt,fetch,zbrnch,allfin 422 71DE A086 422 71E0 6830 422 71E2 65F6 422 71E4 71EE 423 71E6 7204 data isserr 424 71E8 60B6 data toterm,begtxt,5 424 71EA 7581 424 71EC 0005 425 426 ; abort if one of the above error conditions exist 427 71EE 65F6 allfin data zbrnch,semi2 ; test unbalanced error flag 427 71F0 71F4 428 71F2 7464 data ab0rt 429 430 ; issue warning if this word is a re-definition... 431 71F4 70B2 semi2 data lit,temp,fetch,zbrnch,semi3 ; skip if not a redefinition 431 71F6 A070 431 71F8 6830 431 71FA 65F6 431 71FC 7200 432 71FE 74B6 data rdferr ; else issue warning if enabled 433 ; end of colon definition, reset compile state... 434 7200 70FA semi3 data lbrack ; go into interpret mode 435 7202 832C data exit 436 437 7204 8320 isserr data docol,cr,error,colnam,unbal 437 7206 6E92 437 7208 752C 437 720A 74CE 437 720C 74AC 438 720E 62BA data plus1 ; set unbalanced error detect to non-zero value 439 7210 832C data exit 440 ;] 441 442 ;[ HIDDEN ( dictionary_address -- ) 443 ; toggles the hidden attribute on the dictionary entry 444 ; normally you would hide a word after defining it with: LATEST @ HIDDEN 445 7212 7180 hidh data semih,6 445 7214 0006 446 7216 4849 text 'HIDDEN' 446 7218 4444 446 721A 454E 447 721C 721E hideme data $+2 448 721E 06A0 bl @bank1 448 7220 8332 449 7222 6D0E data _hide 450 ;] 451 452 ;[ IMMEDIATE -- 79 453 ; Marks the most recently created dictionary entry as a word which will be 454 ; executed when encountered during compilation rather than compiled. 455 7224 7212 immh data hidh,9 455 7226 0009 456 7228 494D text 'IMMEDIATE ' 456 722A 4D45 456 722C 4449 456 722E 4154 456 7230 4520 457 7232 7234 imm data $+2 458 7234 06A0 bl @bank1 458 7236 8332 459 7238 6D1C data _imm 460 ;] 461 462 ;[ ['] -- addr C,I,M,83 "bracket-tick" 463 ; -- (compiling) 464 ; Used in the form: 465 ; [']466 ; Compiles the compilation address addr of as a literal. 467 ; When the colon definition is later executed addr is left on the stack. 468 ; An error condition exists ifis not found in the currently active 469 ; search order. See: LITERAL 470 723A 7224 tickh data immh,immed+3 470 723C 8003 471 723E 5B27 text '[''] ' 471 7240 5D20 472 tick ; data docol,spword,find,drop,litral,exit 473 7242 8320 data docol,getword,litral,exit 473 7244 72BA 473 7246 70C0 473 7248 832C 474 475 ;] 476 477 ;[ ' -- addr M,83 "tick" 478 ; Used in the form: 479 ; '480 ; addr is the compilation address of . 481 ; An error condition exists ifis not found in the currently active 482 ; search order. 483 724A 723A tick2h data tickh,1 483 724C 0001 484 724E 2720 text ''' ' 485 7250 8320 tick2 data docol 486 ; data spword ; get a word from the TIB 487 ; data find ; find it in the dictionary 488 ; data zbrnch,tick2x ; jump if not found 489 ; data exit ; if found, exit, leaving cfa on the stack 490 ; tick2x data drop,lit0,exit ; not found - push 0 491 7252 72BA data getword 492 7254 832C data exit 493 ;] 494 495 ;[ COMPILE -- C,83 496 ; Typically used in the form: 497 ; :... COMPILE ; 498 ; When... is executed, the compilation address compiled for 499 ; compiled and not executed. 500 ;is is typically immediate and 501 ; See: "compilation" 502 7256 724A compih data tick2h,7 502 7258 0007 503 725A 434F text 'COMPILE ' 503 725C 4D50 503 725E 494C 503 7260 4520 504 7262 7264 compile data $+2 505 ; note: the following line of code MUST be executed from bank 0. 506 ; It cannot execute in bank 1 because all the Forth CFAs are in bank 0. 507 7264 C073 mov *pc+,r1 ; get cfa of next word in thread 508 7266 06A0 bl @bank1 ; do the rest in bank 1 508 7268 8332 509 726A 6D36 data _compil ; see 1-09-Compilation.a99 510 ;] 511 512 ;[ [COMPILE] -- C,I,M,79 "bracket-compile" 513 ; -- (compiling) 514 ; Used in the form: 515 ; [COMPILE]is typically not immediate. 516 ; Forces compilation of the following word . 517 ; This allows compilation of an immediate word when it would otherwise have been 518 ; executed. 519 726C 7256 icomph data compih,immed+9 519 726E 8009 520 7270 5B43 text '[COMPILE] ' 520 7272 4F4D 520 7274 5049 520 7276 4C45 520 7278 5D20 521 727A 8320 icomp data docol 522 727C 72B2 data spword ; get a word from TIB 523 727E 6AD8 data find,drop ; find it in the dictionary 523 7280 6172 524 7282 70CC data comma ; compile the CFA to HERE 525 7284 832C data exit 526 ;] 527 528 ;[ RECURSE ( -- ) 529 ; RECURSE makes a recursive call to the current word that is being compiled. 530 ; Normally while a word is being compiled, it is marked HIDDEN so that 531 ; references to the same word within are calls to the previous definition of 532 ; the word. However we still have access to the word which we are currently 533 ; compiling through the LATEST pointer so we can use that to compile a 534 ; recursive call. 535 7286 726C recrsh data icomph,immed+7 535 7288 8007 536 728A 5245 text 'RECURSE ' 536 728C 4355 536 728E 5253 536 7290 4520 537 7292 8320 recurs data docol 538 7294 76DE data lates_,fetch ; get LATEST on stack 538 7296 6830 539 7298 6BF2 data cfa ; convert to CFA 540 729A 70CC data comma ; compile it 541 729C 832C data exit 542 ;] 543 544 ;[ EXECUTE addr -- 79 545 ; The word definition indicated by addr is executed. 546 ; An error condition exists if addr is not a compilation address 547 729E 7286 exeh data recrsh,7 547 72A0 0007 548 72A2 4558 text 'EXECUTE ' 548 72A4 4543 548 72A6 5554 548 72A8 4520 549 72AA 72AC execut data $+2 550 72AC C1B4 mov *stack+,r6 ; pop addr to r6 551 72AE C1F6 mov *r6+,r7 ; get cfa 552 72B0 0457 b *r7 ; execute it 553 ;] 554 555 ; little utility word to get a word using a space as a delimiter. 556 ; Saves a few bytes as it is used in multiple places. 557 72B2 8320 spword data docol,bl_,word,exit 557 72B4 6AC8 557 72B6 6AA2 557 72B8 832C 558 559 560 ; another utility word 561 ; gets a word from the input stream, finds it in the dictionary. 562 ; aborts if the word is not found in the dictionary. 563 72BA 8320 getword data docol 564 72BC 770C data in_,fetch,rspush 564 72BE 6830 564 72C0 6290 565 72C2 72B2 data spword,find,zbrnch,finderr 565 72C4 6AD8 565 72C6 65F6 565 72C8 72D0 566 72CA 62AC data rspop,drop 566 72CC 6172 567 72CE 832C data exit 568 569 72D0 62AC finderr data rspop,in_,store 569 72D2 770C 569 72D4 6852 570 72D6 72B2 data spword,type 570 72D8 6C94 571 72DA 60B6 data toterm,notick,10 571 72DC 72E6 571 72DE 000A 572 72E0 74CE data colnam 573 72E2 7464 data ab0rt 574 72E4 832C data exit 575 72E6 206E notick text ' not found' 575 72E8 6F74 575 72EA 2066 575 72EC 6F75 575 72EE 6E64 * * COPY 'C:\TI\Source\TurboForth\Bank0\0-11-Interpreter.a99' * 1 ; ______ _ _ _____ _ _ 2 ; | ____| | | | | |_ _| | | | | 3 ; | |__ ___ _ __| |_| |__ | | _ __ | |_ ___ _ __ _ __ _ __ ___| |_ ___ _ __ 4 ; | __/ _ \| '__| __| '_ \ | | | '_ \| __|/ _ \ '__| '_ \| '__/ _ \ __|/ _ \ '__| 5 ; | | | (_) | | | |_| | | | _| |_| | | | |_| __/ | | |_) | | | __/ |_| __/ | 6 ; |_| \___/|_| \__|_| |_| |_____|_| |_|\__|\___|_| | .__/|_| \___|\__|\___|_| 7 ; The interpreter/compiler | | 8 ; |_| 9 10 ;[ INTERPRET ( -- ) 11 72F0 729E inth data exeh,9 ; points to execute in Compilation.a99 11 72F2 0009 12 72F4 494E text 'INTERPRET ' 12 72F6 5445 12 72F8 5250 12 72FA 5245 12 72FC 5420 13 72FE 8320 interp data docol 14 7300 70B2 data lit,intvec,fetch,execut ; get the vector for INTERPRET and call it 14 7302 A000 14 7304 6830 14 7306 72AA 15 7308 832C data exit 16 17 ; standard, un-vectored INTERPRET 18 ; (an alternative interpreter can be installed by patching address INTVEC 19 ; defined in 0-22.system.a99) 20 730A 8320 intgo data docol 21 730C 72B2 intlp data spword ; (addr len) get a word from TIB 22 730E 6186 data dup ; (addr len len) 23 7310 65F6 data zbrnch,ok ; (addr len) if len is zero no identifiable 23 7312 7362 24 ; word was found, or TIB is empty 25 ; check the word identified by WORD, see if it's in the dictionary 26 7314 75EE data dup2 ; (addr len addr len) 27 7316 6AD8 data find ; (addr len cfa flag) see if the word is in 28 ; dictionary (flag=0 if not found) 29 7318 6186 data dup ; (addr len cfa flag flag) 30 731A 65F6 data zbrnch,chknum ; (addr len cfa flag) branch if not found 30 731C 734C 31 32 ; the word was found in the dictionary. 33 ; check STATE to see what to do with it. 34 ; (addr len cfa flag) 35 731E 70B2 data lit,_state,fetch ; (addr len cfa flag state) 35 7320 A048 35 7322 6830 36 7324 65F6 data zbrnch,state0 ; (addr len cfa flag) jump if interpreting 36 7326 7338 37 38 ; we're in compile mode (state=1) 39 ; compile the word, UNLESS the word is immediate 40 7328 62BA data plus1 ; (addr len cfa flag) flag=0 if not 41 ; immediate 42 732A 65F6 data zbrnch,nimm ; (addr len cfa) jump if not immediate 42 732C 7344 43 44 ; it's immediate - execute it 45 ; (addr len cfa) 46 732E 61D2 data nip,nip ; clean up stack 46 7330 61D2 47 7332 72AA data execut ; execute the word 48 7334 65E4 data branch,intlp ; repeat 48 7336 730C 49 50 ; we're interpreting. clean up stack and execute 51 ; (addr len cfa flag) 52 7338 6172 state0 data drop,nip,nip ; (cfa) 52 733A 61D2 52 733C 61D2 53 733E 72AA data execut ; (--) 54 7340 65E4 data branch,intlp ; repeat 54 7342 730C 55 ; word is not immediate - compile it 56 ; (addr len cfa) 57 7344 70CC nimm data comma ; (addr len) 58 7346 75E0 data drop2 ; (--) 59 7348 65E4 data branch,intlp ; repeat 59 734A 730C 60 61 ; no word found in dictionary, check to see if it's a number 62 ; on entry: (addr len cfa flag) 63 734C 75E0 chknum data drop2 ; (addr len) 64 734E 75EE data dup2 ; (addr len addr len) 65 7350 6B76 data number ; (addr len number ucc ) 66 7352 65F6 data zbrnch,clean ; (addr len number ) if ucc=0 then number is 66 7354 7366 67 ; on the stack 68 ; clean up stack & check rest of tib 69 70 ; it's not a number or a word so we don't know what it is, error 71 7356 6172 ierr data drop ; (addr len) drop double number 72 7358 752C data error ; type ERROR: to the screen 73 735A 6C94 data type ; echo name of word 74 735C 749E data nferr ; issue not found error 75 735E 6E92 data cr,ab0rt 75 7360 7464 76 77 ; WORD didn't find anything... 78 ; on entry (addr len) 79 7362 75E0 ok data drop2 ; (--) clean up addr & len 80 7364 832C okx data exit 81 82 ; (addr len number ) 83 ; at this point the number is on the top of the stack. 84 ; It may consist of one OR two words, depends if NUMBER returned a 85 ; double or not. 86 ; location isdbl shall be non zero if a double was returned 87 88 7366 70B2 clean data lit,isdbl,fetch ; double on the stack? 88 7368 A052 88 736A 6830 89 736C 65F6 data zbrnch,nodbl ; jump if not 89 736E 737C 90 7370 6190 data rot,drop,rot,drop ; clean up and leave 32 bit number on stack 90 7372 6172 90 7374 6190 90 7376 6172 91 7378 65E4 data branch,clean1 91 737A 738C 92 737C 61D2 nodbl data nip,nip ; clean up and leave 16 bit number on stack 92 737E 61D2 93 94 ; check for CODE: here... 95 7380 70B2 data lit,coding,fetch,zbrnch,nocode,comma 95 7382 A068 95 7384 6830 95 7386 65F6 95 7388 738C 95 738A 70CC 96 97 98 nocode 99 738C 70B2 clean1 data lit,_state,fetch ; ( number state ) get state 99 738E A048 99 7390 6830 100 7392 65F6 data zbrnch,intlp ; ( number ) if not compiling just leave on 100 7394 730C 101 ; the stack 102 7396 70B2 data lit,isdbl,fetch,zbrnch,csing ; jump if not compiling a double 102 7398 A052 102 739A 6830 102 739C 65F6 102 739E 73A4 103 73A0 617C data swap,clc ; compile high word of double 103 73A2 60AC 104 73A4 60AC csing data clc ; ( ) compile a single or low word of double 105 106 73A6 65E4 intout data branch,intlp 106 73A8 730C 107 108 73AA 70B2 badblk data lit,doboot,fetch 108 73AC A04E 108 73AE 6830 109 73B0 65F6 data zbrnch,badbk1 109 73B2 73B6 110 73B4 753A data nobootm ; display no boot message and abort 111 73B6 6E92 badbk1 data cr,toterm,blkmsg,10 111 73B8 60B6 111 73BA 75CB 111 73BC 000A 112 73BE 7796 data ioerr1,hexdot 112 73C0 7880 113 73C2 7464 noboot data ab0rt 114 ;] 115 116 ;[ STK? ( -- ) 117 ; checks stack for underflow, aborts if underflow, else does nothing 118 73C4 72F0 stkufh data inth,4 118 73C6 0004 119 73C8 5354 text 'STK?' 119 73CA 4B3F 120 73CC 8320 stkuf data docol,depth,ltz,zbrnch,stkx 120 73CE 6240 120 73D0 64F0 120 73D2 65F6 120 73D4 73E2 121 73D6 752C data error,toterm,stktxt,10,cr,ab0rt 121 73D8 60B6 121 73DA 75AF 121 73DC 000A 121 73DE 6E92 121 73E0 7464 122 73E2 832C stkx data exit 123 ;] 124 125 ;[ FORGET -- M,83 126 ; Used in the form: 127 ; FORGET128 ; If is found in the compilation vocabulary, delete 129 ; dictionary and all words added to the dictionary afterfrom the regardless of 130 ; their vocabulary. 131 73E4 73C4 forgth data stkufh,6 131 73E6 0006 132 73E8 464F text 'FORGET' 132 73EA 5247 132 73EC 4554 133 73EE 8320 forget data docol,spword,find,zbrnch,notfnd ; find word cfa in dictionary 133 73F0 72B2 133 73F2 6AD8 133 73F4 65F6 133 73F6 7424 134 73F8 6C1E data dfa,dup ; get dictionary entry address 134 73FA 6186 135 73FC 6830 data fetch,lates_,store ; update latest 135 73FE 76DE 135 7400 6852 136 7402 76EC data here_,store ; update H 136 7404 6852 137 7406 70EC data align ; force update of appropriate hi or low mem pointer 138 7408 780E forg1 data ghere ; save HERE 139 740A 7750 data ffaih,fetch,here_,store,align ; force update of FFAIHM 139 740C 6830 139 740E 76EC 139 7410 6852 139 7412 70EC 140 7414 7766 data ffaml,fetch,here_,store,align ; force update of FFAILM 140 7416 6830 140 7418 76EC 140 741A 6852 140 741C 70EC 141 741E 76EC data here_,store ; restore here 141 7420 6852 142 7422 832C data exit 143 7424 6172 notfnd data drop,exit ; take no action if not found 143 7426 832C 144 ;] 145 146 ;[ ABORT" flag -- C,I,83 "abort-quote" 147 ; -- (compiling) 148 ; Used in the form: 149 ; flag ABORT" ccc" 150 ; When later executed, if flag is true the characters ccc, delimited by " 151 ; (close-quote), are displayed and then a system dependent error abort sequence, 152 ; including the function of ABORT , is performed. 153 ; If flag is false, the flag is dropped and execution continues. 154 ; The blank following ABORT" is not part of ccc. 155 7428 73E4 aborth data forgth,immed+6 155 742A 8006 156 742C 4142 abttxt text 'ABORT"' 156 742E 4F52 156 7430 5422 157 7432 8320 abort data docol,string,compile,rot,compile,zbrnch,ghere,lit,4,add,comma 157 7434 7900 157 7436 7262 157 7438 6190 157 743A 7262 157 743C 65F6 157 743E 780E 157 7440 70B2 157 7442 0004 157 7444 631E 157 7446 70CC 158 7448 7262 data compile,abort_,compile,drop2,exit 158 744A 7452 158 744C 7262 158 744E 75E0 158 7450 832C 159 7452 8320 abort_ data docol,type,cr,ab0rt 159 7454 6C94 159 7456 6E92 159 7458 7464 160 ;] 161 162 ;[ ABORT 79 163 ; Clears the data stack and performs the function of QUIT. 164 ; No message is displayed. 165 745A 7428 ab0rth data aborth,5 165 745C 0005 166 745E 4142 text 'ABORT ' 166 7460 4F52 166 7462 5420 167 7464 8320 ab0rt data docol 168 7466 6E92 data cr,s0_,sps,lbrack,clsall 168 7468 77B4 168 746A 76A8 168 746C 70FA 168 746E 7496 169 7470 7B4E data blk,store0 ; reset block to 0 in case we're loading 169 7472 6892 170 7474 70B2 data lit,lstblk,store0 170 7476 A1B4 170 7478 6892 171 747A 70B2 data lit,tib,tib_,store ; reset address of terminal input buffer 171 747C 3420 171 747E 773E 171 7480 6852 172 7482 770C data in_,store0 ; set >IN to 0 172 7484 6892 173 7486 70B2 data lit,80,cpl,store ; set 80 characters per line 173 7488 0050 173 748A 7668 173 748C 6852 174 748E 70B2 data lit,source,store0 ; reset EVALUATE source 174 7490 A058 174 7492 6892 175 7494 6124 data quit ; call quit 176 177 7496 7498 clsall data $+2 178 7498 06A0 bl @bank1 ; close all open files 178 749A 8332 179 749C 7B46 data _clall ; see 1-14-File-IO.a99 180 ;] 181 182 ;[ VTYPE ( vdp_addr len -- ) 183 ; types a string stored in vdp to the screen 184 ; vtypeh data ab0rth,5 185 ; text 'VTYPE ' 186 ; vtype data docol,dup,nrot,pad,swap,fvmbr,pad,swap,type,exit 187 ;] * * COPY 'C:\TI\Source\TurboForth\Bank0\0-12-Errors.a99' * 1 ; ______ __ __ 2 ; | ____| | \/ | 3 ; | |__ _ __ _ __ ___ _ __ | \ / | ___ ___ ___ __ _ __ _ ___ ___ 4 ; | __| | '__| '__/ _ \| '__| | |\/| |/ _ | __/ __|/ _` |/ _` |/ _ | __| 5 ; | |____| | | | | (_) | | | | | | __|__ \__ \ (_| | (_| | __|__ \ 6 ; |______|_| |_| \___/|_| |_| |_|\___|___/___/\__,_|\__, |\___|___/ 7 ; Error reporting routines __/ | 8 ; |___/ 9 10 11 ; word not found error, used by INTERPRET 12 749E 8320 nferr data docol,toterm,nftxt,10 ; echo 'not found' 12 74A0 60B6 12 74A2 75A1 12 74A4 000A 13 74A6 608C data lit1,colnam ; report name of colon definition if in a colon 13 74A8 74CE 14 ; definition 15 74AA 832C data exit 16 17 18 ; type the word 'Unbalanced ' to the terminal... used by ; 19 74AC 8320 unbal data docol,toterm,baltxt,11,exit 19 74AE 60B6 19 74B0 7596 19 74B2 000B 19 74B4 832C 20 21 22 ; warning message. issued when a word is re-defined. used by ; 23 74B6 8320 rdferr data docol,warn,fetch,zbrnch,rdfer1 23 74B8 772E 23 74BA 6830 23 74BC 65F6 23 74BE 74CC 24 74C0 6E92 data cr,toterm,rdftxt,10,lit0,colnam ; issue warning 24 74C2 60B6 24 74C4 7586 24 74C6 000A 24 74C8 6084 24 74CA 74CE 25 74CC 832C rdfer1 data exit 26 27 28 ; if we are in a colon definition (state!=0) then echo the name of the 29 ; colon definition (via LATEST), else skip. 30 74CE 8320 colnam data docol 31 74D0 70B2 data lit,_state,fetch,zbrnch,errxit 31 74D2 A048 31 74D4 6830 31 74D6 65F6 31 74D8 7500 32 74DA 65F6 data zbrnch,colnm1 32 74DC 74E4 33 74DE 60B6 data toterm,intxt,4 33 74E0 75AB 33 74E2 0004 34 74E4 70B2 colnm1 data lit,latest,fetch ; get latest 34 74E6 A044 34 74E8 6830 35 74EA 62CE data plus2 ; move to length word 36 74EC 6186 data dup,fetch ; copy address, and fetch length 36 74EE 6830 37 74F0 70B2 data lit,>f,and ; get length only 37 74F2 000F 37 74F4 67D2 38 74F6 617C data swap,plus2 ; compute address of word text 38 74F8 62CE 39 74FA 617C data swap,type,space1 ; type the name to the terminal 39 74FC 6C94 39 74FE 6D38 40 41 errxit ; reports block number if loading... 42 7500 7B4E data blk,fetch,zbrnch,repxit 42 7502 6830 42 7504 65F6 42 7506 752A 43 7508 60B6 data toterm,blctxt,10,lit,lstblk,fetch,udot 43 750A 75B9 43 750C 000A 43 750E 70B2 43 7510 A1B4 43 7512 6830 43 7514 782C 44 7516 6E92 data cr,toterm,linnum,8,in_,fetch,lit,64,sdiv,dot 44 7518 60B6 44 751A 75C3 44 751C 0008 44 751E 770C 44 7520 6830 44 7522 70B2 44 7524 0040 44 7526 63C6 44 7528 783C 45 752A 832C repxit data exit 46 47 48 ; writes "ERROR:" used by all error routines 49 752C 8320 error data docol,cr 49 752E 6E92 50 7530 60B6 data toterm,errtxt,6,cr ; write ERROR: 50 7532 7590 50 7534 0006 50 7536 6E92 51 7538 832C data exit 52 53 753A 8320 nobootm data docol,cr,lit,pabfil,lit,pabnln,chrftc,type 53 753C 6E92 53 753E 70B2 53 7540 A18A 53 7542 70B2 53 7544 A189 53 7546 686E 53 7548 6C94 54 754A 60B6 data toterm,nftxt,10,lit,doboot,store0,ab0rt 54 754C 75A1 54 754E 000A 54 7550 70B2 54 7552 A04E 54 7554 6892 54 7556 7464 55 56 57 ; text for the various error types trapped by ;... 58 7558 4946 iferr text 'IF/THEN' 58 755A 2F54 58 755C 4845 58 755E 4E 59 755F 464F doertx text 'FOR or DO loop' 59 7561 5220 59 7563 6F72 59 7565 2044 59 7567 4F20 59 7569 6C6F 59 756B 6F70 60 756D 4341 castxt text 'CASE/ENDCASE' 60 756F 5345 60 7571 2F45 60 7573 4E44 60 7575 4341 60 7577 5345 61 7579 4F46 oftxt text 'OF/ENDOF' 61 757B 2F45 61 757D 4E44 61 757F 4F46 62 7581 4245 begtxt text 'BEGIN' 62 7583 4749 62 7585 4E 63 64 65 ; general error text... 66 7586 5265 rdftxt text 'Redefined ' 66 7588 6465 66 758A 6669 66 758C 6E65 66 758E 6420 67 7590 4552 errtxt text 'ERROR:' 67 7592 524F 67 7594 523A 68 7596 556E baltxt text 'Unbalanced ' 68 7598 6261 68 759A 6C61 68 759C 6E63 68 759E 6564 68 75A0 20 69 75A1 206E nftxt text ' not found' 69 75A3 6F74 69 75A5 2066 69 75A7 6F75 69 75A9 6E64 70 75AB 2069 intxt text ' in ' 70 75AD 6E20 71 75AF 556E stktxt text 'Underflow!' 71 75B1 6465 71 75B3 7266 71 75B5 6C6F 71 75B7 7721 72 75B9 2069 blctxt text ' in block ' 72 75BB 6E20 72 75BD 626C 72 75BF 6F63 72 75C1 6B20 73 75C3 6F6E linnum text 'on line ' 73 75C5 206C 73 75C7 696E 73 75C9 6520 74 75CB 494F blkmsg text 'IO error #' 74 75CD 2065 74 75CF 7272 74 75D1 6F72 74 75D3 2023 75 76 75D5 0000 even * * COPY 'C:\TI\Source\TurboForth\Bank0\0-13-Double.a99' * 1 ; ____ ___ _ _ _ __ __ _ 2 ; |___ \__ \ | | (_) | \ \ / / | | 3 ; __) | ) |______| |__ _| |_ \ \ /\ / /___ _ __ __| |___ 4 ; |__ < / /|______| '_ \| | __| \ \/ \/ // _ \| '__/ _` / __| 5 ; ___) / /_ | |_) | | |_ \ /\ /| (_) | | | (_| \__ \ 6 ; |____/____| |_.__/|_|\__| \/ \/ \___/|_| \__,_|___/ 7 8 ; ######################################## 9 ; Double Number Extension Word Set 10 ; Words to provide 32 bit math facilities 11 ; ######################################## 12 ; Note: To save memory, these words may be removed completely and added to a 13 ; support file on disk. 14 15 ;[ 2DROP ( d -- ) 16 75D6 745A drop2h data ab0rth,5 16 75D8 0005 17 75DA 3244 text '2DROP ' 17 75DC 524F 17 75DE 5020 18 75E0 75E2 drop2 data $+2 19 75E2 8D34 c *stack+,*stack+ ; pop 2 words off the stack (cool, eh?) 20 75E4 045C b *next 21 ;] 22 23 ;[ 2DUP ( d -- d d ) 24 75E6 75D6 dup2h data drop2h,4 24 75E8 0004 25 75EA 3244 text '2DUP' 25 75EC 5550 26 75EE 75F0 dup2 data $+2 27 75F0 06A0 bl @bank1 27 75F2 8332 28 75F4 6B0A data _dup2 ; see 1-07-Double.a99 29 ;] 30 31 ; 2SWAP ( a b c d -- c d a b ) * * COPY 'C:\TI\Source\TurboForth\Bank0\0-14-Variables.a99' * 1 2 ; __ __ _ _ _ 3 ; \ \ / / (_) | | | | 4 ; \ \ / /__ _ _ __ _ __ _| |__ | | ___ ___ 5 ; \ \/ // _` | '__| |/ _` | '_ \| |/ _ | __| 6 ; \ /| (_| | | | | (_| | |_) | | __|__ \ 7 ; \/ \__,_|_| |_|\__,_|_.__/|_|\___|___/ 8 9 ;[ UNSIGNED ( -- address ) (variable) 10 ; places the address of the signed number variable on the stack 11 ; this variable is used by the number to string routine to determine if a number should be 12 ; treated as signed or unsigned when converting into a string (normally for displaying). 13 ; If >0, then numbers will be converted as unsigned. This variable is set by U. and . 14 ; but can also be useful in user programs. 15 75F6 75E6 usignh data dup2h,8 15 75F8 0008 16 75FA 554E text 'UNSIGNED' 16 75FC 5349 16 75FE 474E 16 7600 4544 17 7602 7604 usignd data $+2 18 7604 0206 li r6,dotsin 18 7606 A05A 19 7608 102A jmp span1 20 ;] 21 22 ;[ WWRAP ( -- address ) (variable) 23 ; places the address of the WWRAP variable on the stack. 24 ; TYPE observes WWRAP. If WWRAP is false (0) then TYPE will not apply word wrap 25 ; to the typed line. When WWRAP<>0 then word wrap behaviour will be applied. 26 760A 75F6 wwraph data usignh,5 26 760C 0005 27 760E 5757 text 'WWRAP ' 27 7610 5241 27 7612 5020 28 7614 7616 wwrap data $+2 29 7616 0206 li r6,_wwrap 29 7618 A00A 30 761A 1021 jmp span1 31 ;] 32 33 ;[ #BUF ( -- address ) (variable) 34 ; number of disk buffers - minimum is one 35 761C 760A nbufh data wwraph,4 35 761E 0004 36 7620 2342 text '#BUF' 36 7622 5546 37 7624 7626 nbuf data $+2 38 7626 0206 li r6,totblk 38 7628 A1B0 39 762A 1019 jmp span1 40 ;] 41 42 ;[ SSCROLL ( -- address ) (variable) 43 ; places address of NOSCROLL variable on the stack 44 ; used to determine if the command line environment 45 762C 761C noscrh data nbufh,7 45 762E 0007 46 7630 5353 text 'SSCROLL ' 46 7632 4352 46 7634 4F4C 46 7636 4C20 47 7638 763A noscr data $+2 48 763A 0206 li r6,noscrl 48 763C A026 49 763E 100F jmp span1 50 ;] 51 52 ;[ CSEN ( -- address ) (variable) 53 ; places address of CASE variable on the stack 54 ; When CSEN>0 the system is case sensitive 55 7640 762C sensh data noscrh,4 55 7642 0004 56 7644 4353 text 'CSEN' 56 7646 454E 57 7648 764A sens data $+2 58 764A 0206 li r6,cassen 58 764C A056 59 764E 1007 jmp span1 60 ;] 61 62 ;[ SPAN -- addr U,83 "number-t-i-b" 63 ; The address of a variable containing the number of bytes placed into the text input buffer by EXPECT. 64 7650 7640 htibh data sensh,4 64 7652 0004 65 7654 5350 text 'SPAN' 65 7656 414E 66 7658 765A span data $+2 67 765A 0206 li r6,_span 67 765C A04C 68 765E 107B span1 jmp dovar 69 ;] 70 71 ;[ #TIB ( -- address ) (variable) 72 ; returns a pointer to the size of the text input buffer 73 7660 7650 cplh data HTIBH,4 73 7662 0004 74 7664 2354 text '#TIB' 74 7666 4942 75 7668 766A cpl data $+2 76 766A 0206 li r6,tibsiz 76 766C A04A 77 766E 1073 jmp dovar 78 ;] 79 80 ;[ WRAP ( -- address ) (variable) 81 ; places address of WRAP variable on the stack 82 ; used to determine if the SCROLL command does wrap-around or not 83 7670 7660 wraph data cplh,4 83 7672 0004 84 7674 5752 text 'WRAP' 84 7676 4150 85 7678 767A wrap_ data $+2 86 767A 0206 li r6,wrap 86 767C A030 87 767E 106B jmp dovar 88 ;] 89 90 ;[ ZEROS ( -- address ) (variable) 91 ; places address of LZI variable on the stack 92 ; used to set if leading zeros are displyed when displaying numbers 93 7680 7670 zerosh data wraph,5 93 7682 0005 94 7684 5A45 text 'ZEROS ' 94 7686 524F 94 7688 5320 95 768A 768C zeros data $+2 96 768C 0206 li r6,lzi 96 768E A062 97 7690 1062 jmp dovar 98 ;] 99 100 ;[ SP@ ( -- address ) (constant) 101 ; places current address of stack pointer on the stack 102 7692 7680 spfh data zerosh,3 102 7694 0003 103 7696 5350 text 'SP@ ' 103 7698 4020 104 769A 769C spf data $+2 105 769C C184 mov stack,r6 ; address of stack pointer in r6 106 769E 105B jmp dovar 107 ;] 108 109 ;[ SP! ( address -- ) (function) 110 ; set stack pointer address - use with caution! 111 76A0 7692 spsh data spfh,3 111 76A2 0003 112 76A4 5350 text 'SP! ' 112 76A6 2120 113 76A8 76AA sps data $+2 114 76AA C114 mov *stack,stack ; set stack pointer 115 76AC C804 mov stack,@s0 ; set S0 115 76AE A01E 116 76B0 0644 spsx dect stack ; adjust for pre-increment 117 76B2 045C b *next 118 ;] 119 120 ;[ RP@ ( -- address ) (variable) 121 ; places current address of return stack pointer on the stack 122 76B4 76A0 rpfh data spsh,3 122 76B6 0003 123 76B8 5250 text 'RP@' 123 76BA 40 124 76BB 0000 EVEN *>>> Assembler Auto-Generated <<< 125 76BC 76BE rpf data $+2 126 76BE C185 mov rstack,r6 ; address of return stack pointer in r6 127 76C0 104A jmp dovar 128 ;] 129 130 ;[ STATE -- addr U,79 131 ; The address of a variable containing the compilation state. A non-zero content indicates 132 ; compilation is occurring, but the value itself is system dependent. A Standard Program 133 ; may not modify this variable. 134 76C2 76B4 stateh data rpfh,5 134 76C4 0005 135 76C6 5354 text 'STATE ' 135 76C8 4154 135 76CA 4520 136 76CC 76CE state_ data $+2 137 76CE 0206 li r6,_state 137 76D0 A048 138 76D2 1041 jmp dovar 139 ;] 140 141 ;[ LATEST ( -- address ) (variable) 142 ; returns the *address* of LATEST on the stack 143 76D4 76C2 latesh data stateh,6 143 76D6 0006 144 76D8 4C41 text 'LATEST' 144 76DA 5445 144 76DC 5354 145 76DE 76E0 lates_ data $+2 146 76E0 0206 li r6,latest 146 76E2 A044 147 76E4 1038 jmp dovar 148 ;] 149 150 ;[ H ( -- address ) (variable) 151 ; returns the *address* of HERE on the stack - note lowercase 152 ; see the constant, HERE 153 76E6 76D4 hereh data latesh,1 153 76E8 0001 154 76EA 4820 text 'H ' 155 76EC 76EE here_ data $+2 156 76EE 0206 li r6,here 156 76F0 A046 157 76F2 1031 jmp dovar 158 ;] 159 160 ;[ BASE -- addr U,83 161 ; The address of a variable containing the current numeric conversion radix. 162 ; {{2..36}} 163 76F4 76E6 baseh data hereh,4 163 76F6 0004 164 76F8 4241 text 'BASE' 164 76FA 5345 165 76FC 76FE base_ data $+2 166 76FE 0206 li r6,base 166 7700 A05C 167 7702 1029 jmp dovar 168 ;] 169 170 ;[ >IN -- addr U,79 "to-in" 171 ; The address of a variable which contains the present character offset within 172 ; the input stream {{0..the number of characters in the input stream}}. 173 ; See: WORD 174 7704 76F4 inh data baseh,3 174 7706 0003 175 7708 3E49 text '>IN ' 175 770A 4E20 176 770C 770E in_ data $+2 177 770E 0206 li r6,in 177 7710 A042 178 7712 1021 jmp dovar 179 ;] 180 181 ;[ KMODE ( -- address ) (variable) 182 ; returns the address of keydev, the keyscan mode 183 7714 7704 kmodh data inh,5 183 7716 0005 184 7718 4B4D text 'KMODE ' 184 771A 4F44 184 771C 4520 185 771E 7720 kmode data $+2 186 7720 0206 li r6,keydev 186 7722 A022 187 7724 1018 jmp dovar 188 ;] 189 190 ;[ WARN ( -- address ) (variable) 191 ; returns the address of keydev, the keyscan mode 192 7726 7714 warnh data kmodh,4 192 7728 0004 193 772A 5741 text 'WARN' 193 772C 524E 194 772E 7730 warn data $+2 195 7730 0206 li r6,_warn 195 7732 A066 196 7734 1010 jmp dovar 197 ;] 198 199 ;[ TIB -- addr 83 "t-i-b" 200 ; The address of the text input buffer. 201 ; This buffer is used to hold characters when the input stream is coming from 202 ; the current input device. The minimum capacity of TIB is 80 characters. 203 ; Note: TIB is a VDP address, unless SOURCE=-1, in which case it is interpreted 204 ; as a CPU address. 205 7736 7726 tibh data warnh,3 205 7738 0003 206 773A 5449 text 'TIB ' 206 773C 4220 207 773E 7740 tib_ data $+2 208 7740 0206 li r6,tibadr 208 7742 A1CE 209 7744 1008 jmp dovar 210 ;] 211 212 ;[ FFAIHM ( -- address ) 213 ; returns the first free address in high memory 214 7746 7736 ffahh data tibh,6 214 7748 0006 215 774A 4646 text 'FFAIHM' 215 774C 4149 215 774E 484D 216 7750 7752 ffaih data $+2 217 7752 0206 li r6,ffaihm 217 7754 A01C 218 ; fall down into dovar... 219 ;] 220 221 ; DOVAR: common routine used by variables and constants to push their data onto 222 ; the stack. NOTE: this code is also used by code in Variables.a99 223 ; This code is placed here so that it falls within the 256 byte JMP limit of 224 ; both Constants.a99 and Variables.a99 - sneaky ;-) 225 7756 0644 dovar dect stack ; new stack entry 226 7758 C506 mov r6,*stack ; move value to data stack 227 775A 045C b *next 228 229 ;[ FFAILM ( -- address ) 230 ; returns the first free address in low memory 231 775C 7746 ffalh data ffahh,6 231 775E 0006 232 7760 4646 text 'FFAILM' 232 7762 4149 232 7764 4C4D 233 7766 7768 ffaml data $+2 234 7768 0206 li r6,ffailm 234 776A A01A 235 776C 10F4 jmp dovar 236 ;] 237 238 239 ; _____ _ _ 240 ; / ____| | | | | 241 ; | | ___ _ __ ___| |_ __ _ _ __ | |_ ___ 242 ; | | / _ \| '_ \/ __| __|/ _` | '_ \| __/ __| 243 ; | |____| (_) | | | \__ \ |_| (_| | | | | |_\__ \ 244 ; \_____|\___/|_| |_|___/\__|\__,_|_| |_|\__|___/ 245 246 ;[ PAD -- addr 83 247 ; The lower address of a scratch area used to hold data for intermediate 248 ; processing. 249 ; The address or contents of PAD may change and the data lost if the address of 250 ; the next available dictionary location is changed. 251 ; The minimum capacity of PAD is 84 characters. 252 776E 775C padh data ffalh,3 252 7770 0003 253 7772 5041 text 'PAD ' 253 7774 4420 254 7776 7778 pad data $+2 255 7778 C1A0 mov @ffaihm,r6 ; get first free address in HIGH memory 255 777A A01C 256 777C 0286 ci r6,>ffa8 ; compare to end of low memory-86 bytes 256 777E FFA8 257 7780 1102 jlt padx ; if less than then ok, just exit 258 ; otherwise, we're close to end of high memory, so... 259 7782 C1A0 mov @ffailm,r6 ; offer an address in low memory 259 7784 A01A 260 7786 0226 padx ai r6,80 ; add a margin 260 7788 0050 261 778A 10E5 jmp dovar 262 ;] 263 264 ;[ IOERR ( -- io_error ) (constant) 265 ; places last IO error code on the stack 266 778C 776E ioerrh data padh,5 266 778E 0005 267 7790 494F text 'IOERR ' 267 7792 4552 267 7794 5220 268 7796 7798 ioerr1 data $+2 269 7798 C1A0 mov @errnum,r6 269 779A A038 270 779C 10DC jmp dovar 271 ;] 272 273 ;[ XMAX ( -- xmax ) (constant) 274 ; places the horizontal screen size (32, 40 or 80) on the stack 275 779E 778C xmaxh data ioerrh,4 275 77A0 0004 276 77A2 584D text 'XMAX' 276 77A4 4158 277 77A6 77A8 gxmax data $+2 278 77A8 C1A0 mov @xmax,r6 278 77AA A02C 279 77AC 10D4 jmp dovar 280 ;] 281 282 ;[ S0 ( -- address ) (constant) 283 ; *BEGINNING* address of data stack on data stack, used to reset the data stack 284 77AE 779E s0h data xmaxh,2 284 77B0 0002 285 77B2 5330 text 'S0' 286 77B4 77B6 s0_ data $+2 287 77B6 C1A0 mov @S0,r6 ; S0 defined in system.a99 287 77B8 A01E 288 77BA 10CD jmp dovar 289 ;] 290 291 ;[ HEX ( -- ) (function) 292 ; sets the number base to 16 decimal 293 77BC 77AE hexh data s0h,3 293 77BE 0003 294 77C0 4845 text 'HEX ' 294 77C2 5820 295 77C4 77C6 hex data $+2 296 77C6 0200 li r0,16 296 77C8 0010 297 77CA C800 mov r0,@base 297 77CC A05C 298 77CE 045C b *next 299 ;] 300 301 ;[ DECIMAL ( -- ) (function) 302 ; sets the number base to 10 decimal 303 77D0 77BC dech data hexh,7 303 77D2 0007 304 77D4 4445 text 'DECIMAL ' 304 77D6 4349 304 77D8 4D41 304 77DA 4C20 305 77DC 77DE deci data $+2 306 77DE 0200 li r0,10 306 77E0 000A 307 77E2 C800 mov r0,@base 307 77E4 A05C 308 77E6 045C b *next 309 ;] 310 311 ;[ TRUE ( -- flag ) (constant) 312 ; places TRUE (>FFFF) on the stack 313 77E8 77D0 trueh data dech,4 313 77EA 0004 314 77EC 5452 text 'TRUE' 314 77EE 5545 315 77F0 77F2 true data $+2 316 77F2 0706 seto r6 317 77F4 10B0 jmp dovar 318 ;] 319 320 ;[ FALSE ( -- flag ) (constant) 321 ; places FALSE (>0) on the stack 322 77F6 77E8 falseh data trueh,5 322 77F8 0005 323 77FA 4641 text 'FALSE ' 323 77FC 4C53 323 77FE 4520 324 7800 7802 false data $+2 325 7802 04C6 clr r6 326 7804 10A8 jmp dovar 327 ;] 328 329 ;[ HERE ( -- addr ) (constant) 330 ; places the current compilation address on the stack 331 ; see the variable here (lower case) which allows the 332 ; current compilation address to be changed 333 7806 77F6 hhereh data falseh,4 333 7808 0004 334 780A 4845 text 'HERE' 334 780C 5245 335 780E 7810 ghere data $+2 336 7810 C1A0 mov @here,r6 336 7812 A046 337 7814 10A0 jmp dovar 338 ;] 339 340 ;[ RND ( limit -- n) 341 ; pushes a pseudo random number between 0 and limit-1 (rnd MOD limit) 342 ; For the full range (0-65535) use a limit of 0 343 7816 7806 rndh data hhereh,3 343 7818 0003 344 781A 524E text 'RND ' 344 781C 4420 345 781E 7820 rnd data $+2 346 7820 06A0 bl @bank1 346 7822 8332 347 7824 6D42 data _rnd 348 ;] * * COPY 'C:\TI\Source\TurboForth\Bank0\0-15-Strings.a99' * 1 ; _____ _ _ __ __ _ 2 ; / ____| | (_) \ \ / / | | 3 ; | (___ | |_ _ __ _ _ __ __ _ \ \ /\ / /___ _ __ __| |___ 4 ; \___ \| __| '__| | '_ \ / _` | \ \/ \/ // _ \| '__/ _` / __| 5 ; ____) | |_| | | | | | | (_| | \ /\ /| (_) | | | (_| \__ \ 6 ; |_____/ \__|_| |_|_| |_|\__, | \/ \/ \___/|_| \__,_|___/ 7 ; __/ | 8 ; |___/ 9 ; string related words 10 11 ;[ U. u -- M,79 "u-dot" 12 ; u is displayed as an unsigned number in a free-field format. 13 7826 7816 udoth data rndh,2 13 7828 0002 14 782A 552E text 'U.' 15 782C 8320 udot data docol,usign,type,space1,exit 15 782E 78B4 15 7830 6C94 15 7832 6D38 15 7834 832C 16 ;] 17 18 ;[ . n -- M,79 "dot" 19 ; The absolute value of n is displayed in a free field format with a leading 20 ; minus sign if n is negative. 21 7836 7826 doth data udoth,1 21 7838 0001 22 783A 2E20 text '. ' 23 783C 8320 dot data docol,sign 23 783E 78AC 24 7840 6C94 dot1 data type,space1,exit 24 7842 6D38 24 7844 832C 25 ;] 26 27 ;[ U.R ( num width -- ) 28 7846 7836 udotrh data doth,3 28 7848 0003 29 784A 552E text 'U.R ' 29 784C 5220 30 784E 8320 udotr data docol 31 7850 617C data swap \ width num 32 7852 78B4 data usign \ width addr len 33 7854 786C data setw \ addr len 34 7856 65E4 data branch,dot1 34 7858 7840 35 ;] 36 37 ;[ .R ( num width --) 38 785A 7846 dotrh data udotrh,2 38 785C 0002 39 785E 2E52 text '.R' 40 7860 8320 dotr data docol 41 7862 617C data swap \ width num 42 7864 78AC data sign \ width addr len 43 7866 786C data setw \ addr len 44 7868 65E4 data branch,dot1 44 786A 7840 45 ;] 46 47 ;[ subroutines used by . U. .R and U.R 48 786C 8320 setw data docol,rot,swap,tuck,sub,spces,exit 48 786E 6190 48 7870 617C 48 7872 61E0 48 7874 6326 48 7876 6D52 48 7878 832C 49 ;] 50 51 ;[ $. ( num -- ) 52 ; prints a number as an unsigned hex value 53 787A 785A hdoth data dotrh,2 53 787C 0002 54 787E 242E text '$.' 55 7880 8320 hexdot data docol 56 7882 76FC data base_,fetch,swap 56 7884 6830 56 7886 617C 57 7888 77C4 data hex 58 788A 78B4 data usign,type 58 788C 6C94 59 788E 6D38 data space1 60 7890 76FC data base_,store,exit 60 7892 6852 60 7894 832C 61 ;] 62 63 ;[ N>S ( num -- addr len ) 64 ; Takes a number off the stack and converts it to a signed string equivalent, 65 ; with respect to the current number base. 66 ; The variable UNSIGNED is checked, and if true, the strings generated shall be 67 ; the unsigned equivalents of the number on the stack, otherwise the string 68 ; shall be the signed equivalent of the number of the stack. 69 ; 70 ; sign and usign below are entry points into N>S for . and U. respectively to 71 ; force N>S to produce an appropriately signed string. 72 7896 787A ntsh data hdoth,3 72 7898 0003 73 789A 4E3E text 'N>S ' 73 789C 5320 74 789E 78A0 nts data $+2 75 78A0 C820 mov @dotsin,@dosign ; set/reset signed/unsigned mode according to 75 78A2 A05A 75 78A4 A064 76 ; the Forth variable UNSIGNED 77 78A6 06A0 nts1 bl @bank1 77 78A8 8332 78 78AA 6DEC data _nts ; see 1-10-Strings.a99 79 ; entry points for . and U. : 80 78AC 78AE sign data $+2 81 78AE 04E0 clr @dosign 81 78B0 A064 82 78B2 10F9 jmp nts1 83 78B4 78B6 usign data $+2 84 78B6 0720 seto @dosign 84 78B8 A064 85 78BA 10F5 jmp nts1 86 ;] 87 88 ;[ CHAR ( -- ascii ) 89 ; puts the ASCII code of the first character of the following word on the stack 90 ; For example CHAR A puts 65 on the stack. 91 78BC 7896 charh data ntsh,immed+4 91 78BE 8004 92 78C0 4348 text 'CHAR' 92 78C2 4152 93 78C4 8320 char data docol,spword,drop,chrftc,exit 93 78C6 72B2 93 78C8 6172 93 78CA 686E 93 78CC 832C 94 ;] 95 96 ;[ ASCII ( ascii -- ) 97 ; In interpretation state: 98 ; pushes the ascii value of the character immediately following 99 ; ASCII to the stack. 100 ; In compilation state: 101 ; compiles the ascii value of the character immediately following 102 ; ASCII as a literal 103 78CE 78BC asciih data charh,immed+5 103 78D0 8005 104 78D2 4153 text 'ASCII ' 104 78D4 4349 104 78D6 4920 105 78D8 8320 ascii data docol,char,state_,fetch,zbrnch,asciix 105 78DA 78C4 105 78DC 76CC 105 78DE 6830 105 78E0 65F6 105 78E2 78E6 106 78E4 60AC data clc ; compile lit , 107 78E6 832C asciix data exit 108 ;] 109 110 ;[ COUNT addr1 -- addr2 +n 79 111 ; addr2 is addr1+1 and +n is the length of the counted string at addr1. 112 ; The byte at addr1 contains the byte count +n. 113 ; Range of +n is {0.255} See: "string, counted" 114 78E8 78CE counth data asciih,5 114 78EA 0005 115 78EC 434F text 'COUNT ' 115 78EE 554E 115 78F0 5420 116 78F2 78F4 count data $+2 117 78F4 06A0 bl @bank1 117 78F6 8332 118 78F8 6D60 data _count ; see 1-10-Strings.a99 119 ;] 120 121 ;[ S" Compile time:( -- ) Immediate:( -- address length ) 122 ; When Compiling: 123 ; compiles: (S")124 ; e.g S" HELLO" compiles (S") 5 H E L L O 125 ; Note the 0 padding byte for odd length strings. 126 ; The length is a BYTE. At the end of string compilation, HERE is aligned to an 127 ; even address. 128 ; At run time, (S") pushes the address of the beginning of the string 129 ;(address of length byte+1) and the length to the stack. 130 ; 131 ; When Interpreting: 132 ; Compiles the string to the address PAD, and pushes the address and 133 ; length to the stack. 134 78FA 78E8 strngh data counth,immed+2 134 78FC 8002 135 78FE 5322 text 'S"' 136 7900 8320 string data docol,lit,34,word,pad,strng1,exit 136 7902 70B2 136 7904 0022 136 7906 6AA2 136 7908 7776 136 790A 790E 136 790C 832C 137 790E 7910 strng1 data $+2 138 7910 06A0 bl @bank1 138 7912 8332 139 7914 6D8C data _strin ; see 1-10-Strings.a99 140 141 ; (S") ( -- addr len ) 142 ; internal string. S" compiles (S") into a word 143 ; At run time, (S") pushes the address and length of the string following it 144 ; to the stack. 145 7916 78FA strh data strngh,4 145 7918 0004 146 791A 2853 text '(S")' 146 791C 2229 147 791E 7920 str data $+2 148 7920 06A0 bl @bank1 148 7922 8332 149 7924 6DD2 data _str ; see 1-10-Strings.a99 150 ;] 151 152 ;[ -TRAILING addr +n1 -- addr +n2 79 "dash-trailing" 153 ; The character count +n1 of a text string beginning at addr is adjusted to 154 ; exclude trailing spaces. 155 ; If +n1 is zero, then +n2 is also zero. 156 ; If the entire string consists of spaces, then +n2 is zero. 157 7926 7916 trailh data strh,9 157 7928 0009 158 792A 2D54 text '-TRAILING ' 158 792C 5241 158 792E 494C 158 7930 494E 158 7932 4720 159 7934 7936 trail data $+2 160 7936 06A0 bl @bank1 160 7938 8332 161 793A 6D6E data _trail ; see 1-10-Strings.a99 162 ;] 163 164 ;[ ." -- C,I,83 "dot-quote" 165 ; -- (compiling) 166 ; Used in the form: 167 ; ." ccc" 168 ; Later execution will display the characters ccc up to but not including the 169 ; delimiting " (close-quote). The blank following ." is not part of ccc. 170 793C 7926 tstrh data trailh,immed+2 170 793E 8002 171 7940 2E22 text '."' 172 7942 8320 typstr data docol 173 7944 7900 data string,state_,fetch,zbrnch,typst1,compile 173 7946 76CC 173 7948 6830 173 794A 65F6 173 794C 7950 173 794E 7262 174 7950 6C94 typst1 data type,exit 174 7952 832C 175 176 177 178 179 ;] * * COPY 'C:\TI\Source\TurboForth\Bank0\0-16-Graphics.a99' * 1 ; _____ _ _ __ __ _ 2 ; / ____| | | (_) \ \ / / | | 3 ; | | __ _ __ __ _ _ __ | |__ _ ___ ___ \ \ /\ / /___ _ __ __| |___ 4 ; | | |_ | '__/ _` | '_ \| '_ \| |/ __/ __| \ \/ \/ // _ \| '__/ _` / __| 5 ; | |__| | | | (_| | |_) | | | | | (__\__ \ \ /\ /| (_) | | | (_| \__ \ 6 ; \_____|_| \__,_| .__/|_| |_|_|\___|___/ \/ \/ \___/|_| \__,_|___/ 7 ; | | 8 ; |_| 9 ; graphics related commands 10 ; the guts of these commands is in bank1 in 1-03-Graphics.a99 11 12 ;[ GMODE ( graphics_mode -- ) 13 7954 793C gmodeh data tstrh,5 13 7956 0005 14 7958 474D text 'GMODE ' 14 795A 4F44 14 795C 4520 15 795E 7960 gmode data $+2 16 7960 06A0 bl @bank1 16 7962 8332 17 7964 6192 data _gmode ; see 1-03-Graphics.a99 18 ;] 19 20 ;[ HCHAR ( y x ascii count -- ) 21 7966 7954 hcharh data gmodeh,5 21 7968 0005 22 796A 4843 text 'HCHAR ' 22 796C 4841 22 796E 5220 23 7970 7972 hchar data $+2 24 7972 06A0 bl @bank1 24 7974 8332 25 7976 6250 data _hchar ; see 1-03-Graphics.a99 26 ;] 27 28 ;[ VCHAR ( y x ascii count -- ) 29 7978 7966 vcharh data hcharh,5 29 797A 0005 30 797C 5643 text 'VCHAR ' 30 797E 4841 30 7980 5220 31 7982 7984 vchar data $+2 32 7984 06A0 bl @bank1 32 7986 8332 33 7988 625C data _vchar ; see 1-03-Graphics.a99 34 ;] 35 36 ;[ GCHAR ( y x -- ascii ) 37 798A 7978 gcharh data vcharh,5 37 798C 0005 38 798E 4743 text 'GCHAR ' 38 7990 4841 38 7992 5220 39 7994 7996 gchar data $+2 40 7996 06A0 bl @bank1 40 7998 8332 41 799A 6280 data _gchar ; see 1-03-Graphics.a99 42 ;] 43 44 ;[ DCHAR ( W1..Wx word_count ascii -- ) 45 ; loads words from the stack into VDP memory at the ASCII 46 ; code specified. Equivalent to CALL CHAR in BASIC. 47 799C 798A dcharh data gcharh,5 47 799E 0005 48 79A0 4443 text 'DCHAR ' 48 79A2 4841 48 79A4 5220 49 79A6 79A8 dchar data $+2 50 79A8 06A0 bl @bank1 50 79AA 8332 51 79AC 6298 data _dchar ; see 1-03-Graphics.a99 52 ;] 53 54 ;[ SPRITE ( sprite y x ascii color -- ) 55 ; sprite attribute list begins at 6*80h=300h 56 79AE 799C sprith data dcharh,6 56 79B0 0006 57 79B2 5350 text 'SPRITE' 57 79B4 5249 57 79B6 5445 58 79B8 79BA sprite data $+2 59 79BA 06A0 bl @bank1 59 79BC 8332 60 79BE 62B4 data _sprit ; see 1-03-Graphics.a99 61 ;] 62 63 ;[ MAGNIFY ( x -- ) 64 ; sets sprite magnification: 65 ; only the least significant bits are used: 66 ; bit 7: 1=magnified (0=not magnified) 67 ; bit 6: 1=double size (4 character) 68 ; Remember: TI number their bits backwards! Idiots! 69 79C0 79AE magfyh data sprith,7 69 79C2 0007 70 79C4 4D41 text 'MAGNIFY ' 70 79C6 474E 70 79C8 4946 70 79CA 5920 71 79CC 79CE magfy data $+2 72 79CE 06A0 bl @bank1 72 79D0 8332 73 79D2 62E4 data _magfy ; see 1-03-Graphics.a99 74 ;] 75 76 ;[ SPRCOL ( sprite colour -- ) 77 ; sets the colour of a sprite 78 79D4 79C0 sprclh data magfyh,6 78 79D6 0006 79 79D8 5350 text 'SPRCOL' 79 79DA 5243 79 79DC 4F4C 80 79DE 79E0 sprcol data $+2 81 79E0 06A0 bl @bank1 81 79E2 8332 82 79E4 630E data _spcol ; see 1-03-Graphics.a99 83 ;] 84 85 ;[ SPRLOC ( sprite y x -- ) 86 ; sets the location of a sprite 87 79E6 79D4 sprlch data sprclh,6 87 79E8 0006 88 79EA 5350 text 'SPRLOC' 88 79EC 524C 88 79EE 4F43 89 79F0 79F2 sprloc data $+2 90 79F2 06A0 bl @bank1 90 79F4 8332 91 79F6 632C data _sploc ; see 1-03-Graphics.a99 92 ;] 93 94 ;[ SPRLOC? ( sprite -- y x ) 95 ; gets the location of a sprite 96 79F8 79E6 locsph data sprlch,7 96 79FA 0007 97 79FC 5350 text 'SPRLOC? ' 97 79FE 524C 97 7A00 4F43 97 7A02 3F20 98 7A04 7A06 locspr data $+2 99 7A06 06A0 bl @bank1 99 7A08 8332 100 7A0A 6352 data _spget ; see 1-03-Graphics.a99 101 ;] 102 103 ;[ SPRPAT ( sprite ascii -- ) 104 ; sets the pattern of a sprite 105 7A0C 79F8 sppath data locsph,6 105 7A0E 0006 106 7A10 5350 text 'SPRPAT' 106 7A12 5250 106 7A14 4154 107 7A16 7A18 sprpat data $+2 108 7A18 06A0 bl @bank1 108 7A1A 8332 109 7A1C 6370 data _sppat ; see 1-03-Graphics.a99 110 ;] 111 112 ;[ SPRVEC ( sprite y x -- ) 113 ; sets the Y and X movement vectors for sprite movement with SPRMOV 114 7A1E 7A0C smlsth data sppath,6 114 7A20 0006 115 7A22 5350 text 'SPRVEC' 115 7A24 5256 115 7A26 4543 116 7A28 7A2A smlst data $+2 117 7A2A 06A0 bl @bank1 117 7A2C 8332 118 7A2E 638E data _smlst ; see 1-03-Graphics.a99 119 ;] 120 121 ;[ SPRMOV ( start_sprite number_of_sprites -- ) 122 ; moves sprites according to the entries in SMLIST, starting from start_sprite 123 ; and continuing for number_of_sprites 124 7A30 7A1E sprmvh data smlsth,6 124 7A32 0006 125 7A34 5350 text 'SPRMOV' 125 7A36 524D 125 7A38 4F56 126 7A3A 7A3C sprmov data $+2 127 7A3C 06A0 bl @bank1 127 7A3E 8332 128 7A40 63A4 data _spmov ; see 1-03-Graphics.a99 129 ;] 130 131 ;[ COLOR ( char_set foreground background -- ) 132 ; sets the color sets in 32 column mode 133 7A42 7A30 colorh data sprmvh,5 133 7A44 0005 134 7A46 434F text 'COLOR ' 134 7A48 4C4F 134 7A4A 5220 135 7A4C 7A4E color data $+2 136 7A4E 06A0 bl @bank1 136 7A50 8332 137 7A52 63DE data _color ; see 1-03-Graphics.a99 138 ;] 139 140 ;[ SCREEN ( colour -- ) 141 ; sets the screen colour 142 7A54 7A42 scrnh data colorh,6 142 7A56 0006 143 7A58 5343 text 'SCREEN' 143 7A5A 5245 143 7A5C 454E 144 7A5E 7A60 screen data $+2 145 7A60 06A0 bl @bank1 145 7A62 8332 146 7A64 63F8 data _scren ; see 1-03-Graphics.a99 147 ;] 148 149 ;[ SCROLL ( direction -- ) 150 ; scrolls the panel defined by PANEL in the direction specified 151 ; 0=left 1=right 2=up 3=down 152 7A66 7A54 scrolh data scrnh,6 152 7A68 0006 153 7A6A 5343 text 'SCROLL' 153 7A6C 524F 153 7A6E 4C4C 154 7A70 7A72 scroll data $+2 155 7A72 06A0 bl @bank1 155 7A74 8332 156 7A76 640A data _scrol ; see 1-03-Graphics.a99 157 ;] 158 159 ;[ PANEL ( x y xl yl -- ) 160 ; defines a screen area to be scrolled by SCROLL 161 7A78 7A66 panelh data scrolh,5 161 7A7A 0005 162 7A7C 5041 text 'PANEL ' 162 7A7E 4E45 162 7A80 4C20 163 7A82 7A84 panel data $+2 164 7A84 06A0 bl @bank1 164 7A86 8332 165 7A88 656C data _panel ; see 1-03-Graphics.a99 166 ;] * * COPY 'C:\TI\Source\TurboForth\Bank0\0-17-Speech.a99' * 1 ; _____ _ __ __ _ 2 ; / ____| | | \ \ / / | | 3 ; | (___ _ __ ___ ___ ___| |__ \ \ /\ / /___ _ __ __| |___ 4 ; \___ \| '_ \ / _ \/ _ \/ __| '_ \ \ \/ \/ // _ \| '__/ _` / __| 5 ; ____) | |_) | __/ __/ (__| | | | \ /\ /| (_) | | | (_| \__ \ 6 ; |_____/| .__/ \___|\___|\___|_| |_| \/ \/ \___/|_| \__,_|___/ 7 ; | | 8 ; |_| 9 10 ; these routines are just dictionary entry stubs. 11 ; see 1-04-Speech.a99 for the actual implementation. 12 13 ;[ TALKING? ( -- flag ) 14 ; returns >0 if the speech synth is busy, else returns 0 15 7A8A 7A78 spkngh data panelh,8 15 7A8C 0008 16 7A8E 5441 text 'TALKING?' 16 7A90 4C4B 16 7A92 494E 16 7A94 473F 17 7A96 7A98 spkng data $+2 18 7A98 06A0 bl @bank1 18 7A9A 8332 19 7A9C 662C data _spkng ; see 1-05-Speech.a99 20 ;] 21 22 ;[ SAY ( addr cnt -- ) 23 ; says words from the speech synth's ROM. Use with DATA 24 ; the addresses of the built in words are in ED/AS manual page 422 25 7A9E 7A8A sayh data spkngh,3 25 7AA0 0003 26 7AA2 5341 text 'SAY ' 26 7AA4 5920 27 7AA6 7AA8 say data $+2 28 7AA8 06A0 bl @bank1 28 7AAA 8332 29 7AAC 664E data _say ; see 1-05-Speech.a99 30 ;] 31 32 ;[ STREAM ( addr cnt -- ) 33 ; streams raw speech data to the speech synth. Use with DATA 34 7AAE 7A9E strmh data sayh,6 34 7AB0 0006 35 7AB2 5354 text 'STREAM' 35 7AB4 5245 35 7AB6 414D 36 7AB8 7ABA strm data $+2 37 7ABA 06A0 bl @bank1 37 7ABC 8332 38 7ABE 6668 data _strem ; see 1-05-Speech.a99 39 ;] 40 41 ;[ DATA 42 ; Compiling: DATA ( -- ) Executing: DATA ( -- addr count ) 43 ; E.g. 44 ; When compiling: 45 ; DATA 5 9 8 7 6 5 46 ; Compiles 5 values (9 8 7 6 & 5) to memory 47 ; At runtime: 48 ; When DATA is encountered, will push the start address (the address of 9) 49 ; to the stack, and the count (5). Execution will continue at the word 50 ; immediately following the data list. 51 7AC0 7AAE datah data strmh,immed+4 51 7AC2 8004 52 7AC4 4441 text 'DATA' 52 7AC6 5441 53 7AC8 8320 data docol 54 7ACA 7262 data compile,rtdata ; compile data run-time code 54 7ACC 7AF6 55 7ACE 72B2 data spword,number,drop ; get number of data items from input stream 55 7AD0 6B76 55 7AD2 6172 56 7AD4 6186 data dup,comma ; and append to definition 56 7AD6 70CC 57 58 7AD8 6084 data lit0,do,data2 ; for each data item 58 7ADA 66F6 58 7ADC 7AEA 59 7ADE 72B2 data1 data spword,number,drop ; get number from input stream 59 7AE0 6B76 59 7AE2 6172 60 7AE4 70CC data comma ; append directly to memory 61 7AE6 673E data loop,data1 61 7AE8 7ADE 62 7AEA 832C data2 data exit 63 64 ; (DATA) - run-time code for DATA 65 7AEC 7AC0 rtdath data datah,6 65 7AEE 0006 66 7AF0 2844 text '(DATA)' 66 7AF2 4154 66 7AF4 4129 67 7AF6 7AF8 rtdata data $+2 68 7AF8 06A0 bl @bank1 68 7AFA 8332 69 7AFC 66D6 data _data ; see 1-05-Speech.a99 70 ;] * * COPY 'C:\TI\Source\TurboForth\Bank0\0-18-Blocks.a99' * 1 ; ____ _ _ _____ ______ __ __ _ 2 ; | _ \| | | | |_ _| / / __ \ \ \ / / | | 3 ; | |_) | | ___ ___| | __ | | / / | | | \ \ /\ / /___ _ __ __| |___ 4 ; | _ <| |/ _ \ / __| |/ / | | / /| | | | \ \/ \/ // _ \| '__/ _` / __| 5 ; | |_) | | (_) | (__| < _| |_ / / | |__| | \ /\ /| (_) | | | (_| \__ \ 6 ; |____/|_|\___/ \___|_|\_\ |_____/_/ \____/ \/ \/ \___/|_| \__,_|___/ 7 ; block file system words & subroutines 8 9 ; Notes: 10 ; Since File IO on the TI takes place in VDP RAM, the block system is 11 ; implemented using VDP ram to hold the blocks. In other words, blocks live 12 ; in VDP RAM, *not* CPU ram. Might as well use VDP for something and it has 13 ; the added benefit of leaving *lots* more CPU ram available for Forth code. 14 ; 15 ; The 'system' is designed to support up to six blocks in VDP ram at once. 16 ; I.e. there are six 1K buffers in VDP, each buffer can hold any block. 17 ; The buffers are allocated in sequential order until they are used. When no 18 ; more buffers are available, a previously used buffer is used, it's contents 19 ; are overwritten. However, *if* the contents of a block have been changed 20 ; (i.e. they are more up-to-date than the copy on the disk) the block is 21 ; automatically flushed back to disk before being re-used. 22 ; 23 ; The VDP addresses of the block buffers are defined in 1-15-Initialise.a99 24 ; 25 26 ;[ USE ( addr len -- ) 27 ; Tells the system which block file to use for block IO 28 ; e.g. S" DSK1.BLOCKS" USE 29 ; Simply sets the filename and length in the blockIO PAB 30 7AFE 7AEC useh data rtdath,3 30 7B00 0003 31 7B02 5553 text 'USE ' 31 7B04 4520 32 7B06 8320 use data docol,mtbuf,use1,exit 32 7B08 7CB2 32 7B0A 7B0E 32 7B0C 832C 33 7B0E 7B10 use1 data $+2 34 7B10 06A0 bl @bank1 34 7B12 8332 35 7B14 66EA data _use ; see 1-06-Blocks.a99 36 ;] 37 38 ;[ WHERE ( -- block# ) 39 ; returns the block number of word that has been loaded into memory with LOAD 40 ; eg: WHERE FOO 41 ; can only be used from the command line 42 ; returns 0 if not found, or if the word is in ROM 43 7B16 7AFE whereh data useh,immed+5 43 7B18 8005 44 7B1A 5748 text 'WHERE ' 44 7B1C 4552 44 7B1E 4520 45 7B20 8320 where data docol,spword,find,zbrnch,where1 45 7B22 72B2 45 7B24 6AD8 45 7B26 65F6 45 7B28 7B40 46 7B2A 6C1E data dfa,plus2,fetch,lit,4,rsft,lit,>3ff,and,plus1,exit 46 7B2C 62CE 46 7B2E 6830 46 7B30 70B2 46 7B32 0004 46 7B34 681E 46 7B36 70B2 46 7B38 03FF 46 7B3A 67D2 46 7B3C 62BA 46 7B3E 832C 47 7B40 6172 where1 data drop,lit0,exit 47 7B42 6084 47 7B44 832C 48 ;] 49 50 ;[ BLK -- addr U,79 "b-l-k" 51 ; The address of a variable containing the number of the mass storage block 52 ; being interpreted as the input stream. 53 ; If the value of BLK is zero the input stream is taken from the text input 54 ; buffer. {{0..the number of blocks available -1}} 55 ; See: TIB "input stream" 56 7B46 7B16 blkh data whereh,3 56 7B48 0003 57 7B4A 424C text 'BLK ' 57 7B4C 4B20 58 7B4E 7B50 blk data $+2 59 7B50 0206 li r6,blknum ; address of block variable in ram 59 7B52 A1B2 60 7B54 0460 b @dovar ; push it 60 7B56 7756 61 ;] 62 63 ;[ --> ( -- ) 64 ; loads the next block 65 7B58 7B46 nblkh data blkh,immed+3 65 7B5A 8003 66 7B5C 2D2D text '--> ' 66 7B5E 3E20 67 7B60 8320 nblk data docol 68 7B62 7B4E data blk,fetch,plus1,blk,store,in_,store0 68 7B64 6830 68 7B66 62BA 68 7B68 7B4E 68 7B6A 6852 68 7B6C 770C 68 7B6E 6892 69 7B70 832C data exit 70 ;] 71 72 ;[ THRU ( start end -- ) 73 ; loads blocks start thru end inclusive by calling LOAD for each block. 74 7B72 7B58 thruh data nblkh,4 74 7B74 0004 75 7B76 5448 text 'THRU' 75 7B78 5255 76 7B7A 8320 thru data docol,plus1,swap 76 7B7C 62BA 76 7B7E 617C 77 7B80 66F6 data do,xthru 77 7B82 7B8C 78 7B84 679A thrulp data geti,load 78 7B86 7C18 79 7B88 673E data loop,thrulp 79 7B8A 7B84 80 7B8C 832C xthru data exit 81 ; : THRU ( start-block end-block -- ) 1+ SWAP DO I LOAD LOOP ; 82 ;] 83 84 ;[ BLOCK u -- vdpaddr M,83 85 ; addr is the address of the assigned buffer of the first byte of block u. 86 ; If the block occupying that buffer is not block u and has been UPDATEed it is 87 ; transferred to mass storage before assigning the buffer. 88 ; If block u is not already in memory, it is transferred from mass storage into 89 ; an assigned block buffer. A block may not be assigned to more than one 90 ; buffer. 91 ; If u is not an available block number, an error condition exists. 92 ; Only data within the last buffer referenced by BLOCK or BUFFER is valid. 93 ; The contents of a block buffer must not be changed unless the change may be 94 ; transferred to mass storage.BLOCK ( block# -- addr ) 95 ; 96 ; Brings a block into a buffer, if not already in memory 97 ; 1) If already in memory, the block is not re-loaded from device 98 ; 2) If not in memory: 99 ; 3) Scans for a free buffer 100 ; 4) If no free buffer: 101 ; 5) flush all buffers back to device 102 ; 6) Repeat from 3 103 ; 7) If free buffer: 104 ; 9) Load block from device into free buffer 105 ; 10) Return address of buffer 106 ; 11) If disk error, or block not found etc, return 0 107 7B8E 7B72 blockh data thruh,5 107 7B90 0005 108 7B92 424C text 'BLOCK ' 108 7B94 4F43 108 7B96 4B20 109 7B98 8320 block data docol,lit,blkvec,fetch,execut,exit 109 7B9A 70B2 109 7B9C A002 109 7B9E 6830 109 7BA0 72AA 109 7BA2 832C 110 7BA4 7BA6 block2 data $+2 111 7BA6 06A0 bl @bank1 111 7BA8 8332 112 7BAA 671E data _block ; see 1-06-Blocks.a99 113 ;] 114 115 ;[ LIST ( block# -- ) 116 ; lists a blocks' contents to the screen without loading it 117 7BAC 7B8E listh data blockh,4 117 7BAE 0004 118 7BB0 4C49 text 'LIST' 118 7BB2 5354 119 7BB4 8320 list_ data docol,fblock,dup,zbrnch,lstxit 119 7BB6 7C52 119 7BB8 6186 119 7BBA 65F6 119 7BBC 7BF8 120 7BBE 70B2 data lit,16,lit0 120 7BC0 0010 120 7BC2 6084 121 7BC4 66F6 data do,lstxit 121 7BC6 7BF8 122 7BC8 6E92 list1 data cr,geti,lit,2,dotr 122 7BCA 679A 122 7BCC 70B2 122 7BCE 0002 122 7BD0 7860 123 7BD2 70B2 data lit,3,emit,dup,ghere,lit,64,fvmbr,ghere 123 7BD4 0003 123 7BD6 6D98 123 7BD8 6186 123 7BDA 780E 123 7BDC 70B2 123 7BDE 0040 123 7BE0 6902 123 7BE2 780E 124 7BE4 70B2 data lit,64,trail,type,lit,64,add,break 124 7BE6 0040 124 7BE8 7934 124 7BEA 6C94 124 7BEC 70B2 124 7BEE 0040 124 7BF0 631E 124 7BF2 6C54 125 7BF4 673E data loop,list1 125 7BF6 7BC8 126 7BF8 6172 lstxit data drop,cr,blk,store0,span,fetch,in_,store 126 7BFA 6E92 126 7BFC 7B4E 126 7BFE 6892 126 7C00 7658 126 7C02 6830 126 7C04 770C 126 7C06 6852 127 7C08 70B2 data lit,lstblk,store0,exit 127 7C0A A1B4 127 7C0C 6892 127 7C0E 832C 128 ;] 129 130 ;[ LOAD ( block# -- ) 131 ; interprets a block 132 7C10 7BAC loadh data listh,4 132 7C12 0004 133 7C14 4C4F text 'LOAD' 133 7C16 4144 134 7C18 8320 load data docol 135 7C1A 770C data in_,fetch,rspush 135 7C1C 6830 135 7C1E 6290 136 7C20 7B4E data blk,fetch,rspush 136 7C22 6830 136 7C24 6290 137 7C26 7658 data span,fetch,rspush 137 7C28 6830 137 7C2A 6290 138 7C2C 70B2 data lit,1024,span,store 138 7C2E 0400 138 7C30 7658 138 7C32 6852 139 7C34 770C data in_,store0 139 7C36 6892 140 7C38 7B4E data blk,store 140 7C3A 6852 141 7C3C 72FE data interp 142 7C3E 62AC data rspop,span,store 142 7C40 7658 142 7C42 6852 143 7C44 62AC data rspop,blk,store 143 7C46 7B4E 143 7C48 6852 144 7C4A 62AC data rspop,in_,store 144 7C4C 770C 144 7C4E 6852 145 7C50 832C data exit 146 ;] 147 148 fblock ; ( blk# --) 149 ; fetch block and strip off dirty bit 150 7C52 8320 data docol,block,lit,>7fff,and,exit 150 7C54 7B98 150 7C56 70B2 150 7C58 7FFF 150 7C5A 67D2 150 7C5C 832C 151 152 ;[ CLOAD ( blk -- ) 153 ; Conditionally loads a block if the referenced word (passed in the TIB) is 154 ; not found. 155 ; e.g. 69 CLOAD SAMS? will load block 69 if the word SAMS? is not found. 156 ; If the word *is* found then no further action is taken. 157 7C5E 7C10 cloadh data loadh,immed+5 157 7C60 8005 158 7C62 434C text 'CLOAD ' 158 7C64 4F41 158 7C66 4420 159 7C68 8320 cload data docol,spword,find,nip 159 7C6A 72B2 159 7C6C 6AD8 159 7C6E 61D2 160 7C70 65F6 data zbrnch,cload1 160 7C72 7C78 161 7C74 6172 data drop,exit 161 7C76 832C 162 7C78 7C18 cload1 data load,exit 162 7C7A 832C 163 ;] 164 165 ;[ UPDATE -- 79 166 ; The currently valid block buffer is marked as modified. 167 ; Blocks marked as modified will subsequently be automatically transferred to 168 ; mass storage should its memory buffer be needed for storage of a different 169 ; block or upon execution of FLUSH. 170 7C7C 7C5E updath data cloadh,6 170 7C7E 0006 171 7C80 5550 text 'UPDATE' 171 7C82 4441 171 7C84 5445 172 7C86 7C88 update data $+2 173 7C88 06A0 bl @bank1 173 7C8A 8332 174 7C8C 6840 data _updat ; see 1-06-Blocks.a99 175 ;] 176 177 ;[ FLUSH -- M,83 178 ; Flushes all modified buffers to the storage device then unassigns all block 179 ; buffers. 180 7C8E 7C7C flushh data updath,5 180 7C90 0005 181 7C92 464C text 'FLUSH ' 181 7C94 5553 181 7C96 4820 182 7C98 7C9A flush data $+2 183 7C9A 06A0 bl @bank1 183 7C9C 8332 184 7C9E 67AE data _flush ; see 1-06-Blocks.a99 185 ;] 186 187 ;[ EMPTY-BUFFERS ( -- ) 188 ; immediately sets all buffers to unsaasigned. 189 ; DOES NOT flush dirty buffers to disk 190 7CA0 7C8E mtbufh data flushh,13 190 7CA2 000D 191 7CA4 454D text 'EMPTY-BUFFERS ' 191 7CA6 5054 191 7CA8 592D 191 7CAA 4255 191 7CAC 4646 191 7CAE 4552 191 7CB0 5320 192 7CB2 7CB4 mtbuf data $+2 193 7CB4 06A0 bl @bank1 193 7CB6 8332 194 7CB8 6854 data _mtbuf ; see 1-06-Blocks.a99 195 ;] 196 197 ;[ CLEAN ( buffer -- ) 198 ; forces a buffers' status to clean 199 7CBA 7CA0 cleanh data mtbufh,5 199 7CBC 0005 200 7CBE 434C text 'CLEAN ' 200 7CC0 4541 200 7CC2 4E20 201 7CC4 7CC6 bclean data $+2 202 7CC6 06A0 bl @bank1 202 7CC8 8332 203 7CCA 6870 data _clean ; see 1-06-Blocks.a99 204 ;] 205 206 ;[ DIRTY ( buffer -- ) 207 ; forces a buffers' status to dirty 208 7CCC 7CBA dirtyh data cleanh,5 208 7CCE 0005 209 7CD0 4449 text 'DIRTY ' 209 7CD2 5254 209 7CD4 5920 210 7CD6 7CD8 dirty data $+2 211 7CD8 06A0 bl @bank1 211 7CDA 8332 212 7CDC 687C data _dirty ; see 1-06-Blocks.a99 213 ;] 214 215 ;[ DIRTY? ( buffer -- flag ) 216 ; interrogates a buffers' status, returning true if the buffer is dirty, else 217 ; returning false 218 7CDE 7CCC dirtih data dirtyh,6 218 7CE0 0006 219 7CE2 4449 text 'DIRTY?' 219 7CE4 5254 219 7CE6 593F 220 7CE8 7CEA dirtyq data $+2 221 7CEA 06A0 bl @bank1 221 7CEC 8332 222 7CEE 6888 data _qdirt ; see 1-06-Blocks.a99 223 ;] 224 225 ;[ BLK? ( buffer -- block vdp_address ) 226 ; For a given buffer, returns the actual block stored in that buffer 227 ; and the vdp address of that buffer 228 7CF0 7CDE blkqh data dirtih,4 228 7CF2 0004 229 7CF4 424C text 'BLK?' 229 7CF6 4B3F 230 7CF8 7CFA blkq data $+2 231 7CFA 06A0 bl @bank1 231 7CFC 8332 232 7CFE 689E data _blkq ; see 1-06-Blocks.a99 233 ;] 234 235 ;[ BUF? ( block -- buffer vdp_address ) 236 ; For a given block, return the buffer number, and the vdp address of the buffer 237 ; returns 0 0 if the block is not in memory 238 7D00 7CF0 bufh data blkqh,4 238 7D02 0004 239 7D04 4255 text 'BUF?' 239 7D06 463F 240 7D08 7D0A buf data $+2 241 7D0A 06A0 bl @bank1 241 7D0C 8332 242 7D0E 68B2 data _buf ; see 1-06-Blocks.a99 243 ;] 244 245 ;[ SETBLK ( buffer block -- ) 246 ; For a given buffer, changes the block that it is associated with. 247 ; Allows blocks to copied to other blocks, using FLUSH. 248 ; Blocks can also be copied to a different block file by changing the blocks 249 ; file (with USE) before using FLUSH. 250 7D10 7D00 setblh data bufh,6 250 7D12 0006 251 7D14 5345 text 'SETBLK' 251 7D16 5442 251 7D18 4C4B 252 7D1A 7D1C setblk data $+2 253 7D1C 06A0 bl @bank1 253 7D1E 8332 254 7D20 68E0 data _setbk ; see 1-06-Blocks.a99 255 ;] 256 257 ;[ MKBLK ( block_count -- ) 258 ; makes a block file on disk. 259 ; E.G. 80 MKBLOCK DSK1.BLOCKS 260 ; The above creates an 80K file on disk 1 called BLOCKS. 261 ; use IOERR to check success. 262 ; IOERR contains 0 for success or the disk error code 263 7D22 7D10 mkblkh data setblh,immed+5 263 7D24 8005 264 7D26 4D4B text 'MKBLK ' 264 7D28 424C 264 7D2A 4B20 265 7D2C 8320 mkblk data docol 266 7D2E 72B2 data spword ; get the filename 267 7D30 7D34 data mkblkc,exit ; branch to bank 1 267 7D32 832C 268 7D34 7D36 mkblkc data $+2 269 7D36 06A0 bl @bank1 269 7D38 8332 270 7D3A 68F0 data _mkblk ; see 1-06-Blocks.a99 271 ;] 272 273 ; WriteHeader ( vdp_addr -- vdp_addr+8) 274 ; : WRITE-HEADER ( vdp_addr -- vdp_addr+8) 275 ; $994A VW! LATEST @ VW! HERE VW! 3 PICK VW! ; 276 7D3C 8320 whead data docol 277 7D3E 70B2 data lit,>994a,vdpww,lates_,fetch,vdpww,ghere,vdpww,lit,3,pick,vdpww 277 7D40 994A 277 7D42 7D58 277 7D44 76DE 277 7D46 6830 277 7D48 7D58 277 7D4A 780E 277 7D4C 7D58 277 7D4E 70B2 277 7D50 0003 277 7D52 6212 277 7D54 7D58 278 7D56 832C data exit 279 280 7D58 8320 vdpww data docol ; V2! ( addr val -- addr+2 ) 281 7D5A 6220 data swpb_,swap,dup,nrot,dup2,vdpstr,plus1,swap,swpb_,swap,vdpstr,plus2 281 7D5C 617C 281 7D5E 6186 281 7D60 61AC 281 7D62 75EE 281 7D64 68C0 281 7D66 62BA 281 7D68 617C 281 7D6A 6220 281 7D6C 617C 281 7D6E 68C0 281 7D70 62CE 282 7D72 832C data exit 283 284 285 ; BSAVE ( start_address start_block -- first_free_block) 286 ; : BSAVE ( addr block - next_free_block) 287 ; OVER HERE SWAP - 288 ; BEGIN DUP 1008 > WHILE 289 ; OVER GBASD 290 ; WRITE-HEADER 291 ; 3 PICK 1008 VMBW 292 ; 1008 - ROT 1008 + -ROT SWAP 1+ SWAP 293 ; REPEAT 294 ; SWAP DUP GBASD WRITE-HEADER 3 PICK 3 PICK VMBW 295 ; 1+ NIP NIP FLUSH ; 296 7D74 7D22 bsaveh data mkblkh,5 296 7D76 0005 297 7D78 4253 text 'BSAVE ' 297 7D7A 4156 297 7D7C 4520 298 7D7E 8320 bsave data docol 299 7D80 61C8 data over,ghere,swap,sub 299 7D82 780E 299 7D84 617C 299 7D86 6326 300 7D88 6186 bsave1 data dup,lit,1008,gt,zbrnch,bsave2 300 7D8A 70B2 300 7D8C 03F0 300 7D8E 6488 300 7D90 65F6 300 7D92 7DC2 301 7D94 61C8 data over,block,update 301 7D96 7B98 301 7D98 7C86 302 7D9A 7D3C data whead 303 7D9C 70B2 data lit,3,pick,lit,1008,fvmbw 303 7D9E 0003 303 7DA0 6212 303 7DA2 70B2 303 7DA4 03F0 303 7DA6 6912 304 7DA8 70B2 data lit,1008,sub,rot,lit,1008,add,nrot,swap,plus1,swap 304 7DAA 03F0 304 7DAC 6326 304 7DAE 6190 304 7DB0 70B2 304 7DB2 03F0 304 7DB4 631E 304 7DB6 61AC 304 7DB8 617C 304 7DBA 62BA 304 7DBC 617C 305 7DBE 65E4 data branch,bsave1 305 7DC0 7D88 306 7DC2 617C bsave2 data swap,dup,block,update,whead,lit,3,pick,lit,3,pick,fvmbw 306 7DC4 6186 306 7DC6 7B98 306 7DC8 7C86 306 7DCA 7D3C 306 7DCC 70B2 306 7DCE 0003 306 7DD0 6212 306 7DD2 70B2 306 7DD4 0003 306 7DD6 6212 306 7DD8 6912 307 7DDA 62BA data plus1,nip,nip,flush 307 7DDC 61D2 307 7DDE 61D2 307 7DE0 7C98 308 7DE2 832C data exit 309 310 311 ; BLOAD ( start_block -- ) 312 ; : BLOAD ( block -- next_free_block) 313 ; BEGIN DUP BLOCK DUP VW@ $994A = WHILE 314 ; 2+ DUP VW@ LATEST ! 2+ DUP VW@ H ! 2+ DUP VW@ SWAP 2+ SWAP 315 ; 1008 VMBR 1+ 316 ; REPEAT DROP ; 317 7DE4 7D74 bloadh data bsaveh,5 317 7DE6 0005 318 7DE8 424C text 'BLOAD ' 318 7DEA 4F41 318 7DEC 4420 319 7DEE 8320 data docol 320 7DF0 6186 bload1 data dup,fblock,dup,vdprw,lit,>994a,eq,zbrnch,bload2 320 7DF2 7C52 320 7DF4 6186 320 7DF6 68E8 320 7DF8 70B2 320 7DFA 994A 320 7DFC 647A 320 7DFE 65F6 320 7E00 7E2E 321 7E02 62CE data plus2,dup,vdprw,lates_,store 321 7E04 6186 321 7E06 68E8 321 7E08 76DE 321 7E0A 6852 322 7E0C 62CE data plus2,dup,vdprw,here_,store 322 7E0E 6186 322 7E10 68E8 322 7E12 76EC 322 7E14 6852 323 7E16 62CE data plus2,dup,vdprw,swap,plus2,swap 323 7E18 6186 323 7E1A 68E8 323 7E1C 617C 323 7E1E 62CE 323 7E20 617C 324 7E22 70B2 data lit,1008,fvmbr,plus1 324 7E24 03F0 324 7E26 6902 324 7E28 62BA 325 7E2A 65E4 data branch,bload1 325 7E2C 7DF0 326 7E2E 6172 bload2 data drop 327 7E30 7E34 data memptr ; adjust ffaihm & ffailm as appropriate 328 7E32 832C data exit 329 7E34 7E36 memptr data $+2 330 7E36 C020 mov @here,r0 330 7E38 A046 331 7E3A 06A0 bl @bank1 331 7E3C 8332 332 7E3E 6CDA data mpadj ; see 1-09-Compilation.a99 333 7E40 045C b *next * * COPY 'C:\TI\Source\TurboForth\Bank0\0-19-File-IO.a99' * 1 ; ______ _ _ _____ ______ 2 ; | ____(_) | |_ _| / / __ \ 3 ; | |__ _| | ___ | | / / | | | 4 ; | __| | | |/ _ \ | | / /| | | | 5 ; | | | | | __/ _| |_ / / | |__| | 6 ; |_| |_|_|\___| |_____/_/ \____/ 7 ; File IO implementation 8 9 ;[ FILE ( s_addr s_len buf_addr -- ) 10 ; Builds a PAB in the buffer whose address is passed as buf_addr using the data 11 ; in the string represented by s_addr and s_len. 12 ; For example: 13 ; FBUF: PRINTER 14 ; S" PIO.CR DV80O" PRINTER FILE 15 ; The above builds a PAB in the buffer called PRINTER which references the PIO 16 ; device. Subsequent file IO words that wish to send data to the PIO shall use 17 ; the buffer name to reference it: 18 ; e.g. 19 ; PRINTER #OPEN DROP ( open PIO and drop success/fail flag) 20 ; S" HELLO WORLD" PRINTER #PUT DROP 21 ; ( write HELLO WORLD to the PIO and drop success/fail flag) 22 ; 23 ; Internally, FILE builds a PAB in the buffer which will be used by #OPEN and 24 ; all file IO words. 25 ; Word 0 of the reserved memory is used to point to the actual PAB in VDP 26 ; memory. 27 ; Enough space should be reserved (with ALLOT) in the buffer to hold the PAB 28 ; and the filename. 29 ; 30 ; The string which specifies the file name and file characteristics is defined 31 ; as below. 32 ; The filename *must* come first followed by a space character. 33 ; After that, the file options can be specified in any order. 34 ; 35 ; File Options: 36 ; F=Fixed - Fixed record type 37 ; V=Variable - Variable record type 38 ; 39 ; D=Display - Display data type 40 ; L=InternaL - Internal data type 41 ; 42 ; U=Update - Update file mode 43 ; O=Output - Output file mode 44 ; I=Input - Inoput file mode 45 ; A=Append - Append file mode 46 ; 47 ; S=Sequential - Sequential file type 48 ; R=Relative - Relative file type 49 ; 50 ; Note that Internal type files require L - this is because I is used to 51 ; specify INPUT 52 7E42 7DE4 fileh data bloadh,4 52 7E44 0004 53 7E46 4649 text 'FILE' 53 7E48 4C45 54 7E4A 7E4C file1 data $+2 55 7E4C 06A0 bl @bank1 55 7E4E 8332 56 7E50 78FA data _file ; see 1-14-File-IO.a99 57 ;] 58 59 ;[ FBUF: ( -- ) 60 ; builds a buffer with the name given for use with File IO. 61 ; The buffer is used to hold the PAB during construction by FILE. 62 ; e.g. FBUF: MYFILE 63 ; creates a 42 byte buffer for holding a PAB. 64 ; MYFILE becomes a word in the dictionary which, when executed, returns the 65 ; address of the start of the buffer. 66 ; The buffer is supplied as an input to the file IO words. E.g. 67 ; FBUF: DV80 ( create a 42 byte buffer called DV80) 68 ; S" DSK1.TEST DV80SO" DV80 FILE 69 ; DV80 #OPEN DROP 70 ; S" HELLO WORLD" DV80 #PUT DROP 71 ; DV80 #CLOSE 72 ; 73 7E52 7E42 fbufh data fileh,immed+5 73 7E54 8005 74 7E56 4642 text 'FBUF: ' 74 7E58 5546 74 7E5A 3A20 75 7E5C 8320 fbuf data docol 76 7E5E 6F9A data create ; create dictionary entry 77 7E60 70B2 data lit,42,allot ; reserve 42 bytes 77 7E62 002A 77 7E64 70A2 78 7E66 832C data exit 79 ;] 80 81 ;[ #OPEN ( buf_addr -- t|f ) 82 ; Opens a file with the file name and attributes specified in the buffer 83 ; starting at file_addr. 84 ; The buffer (actually a PAB) is set-up with FILE. 85 ; E.g. FBUF: SERIAL 86 ; S" RS232.BA=9600 DV80SO" SERIAL FILE 87 ; SERIAL #OPEN 88 ; The above shall attempt to open the serial port for output as a Display 89 ; Variable 80 type file. 90 ; 91 ; #OPEN leaves a FALSE on the stack if the file was opened sucessfully. 92 ; If the file could not be opened then it leaves a TRUE on the stack. 93 ; This allows easy trapping with ABORT" as shown below: 94 ; SERIAL #OPEN ABORT" Could not open serial port" 95 ; 96 ; In the event of a file error, IOERR can be read to get the DSR error code. 97 ; If IOERR returns -1 (>FFFF) then this means that no free file IO slots were 98 ; found. A maximum of 3 open files is supported (2 if block files are also to 99 ; be used). 100 ; Note that block files are immediately closed after they are accessed for 101 ; either reading or writing, so 3 generic file io streams are available 102 ; when no blocks files are being used. 103 7E68 7E52 fopenh data fbufh,5 103 7E6A 0005 104 7E6C 234F text '#OPEN ' 104 7E6E 5045 104 7E70 4E20 105 7E72 7E74 fopen1 data $+2 106 7E74 06A0 bl @bank1 106 7E76 8332 107 7E78 79AA data _fopen ; see 1-14-File-IO.a99 108 ;] 109 110 ;[ #CLOSE ( fid -- ) 111 ; closes a file 112 ; Where a file is opened thus: MYFILE #OPEN 113 ; the following will close the same file: MYFILE #CLOSE 114 7E7A 7E68 fclosh data fopenh,6 114 7E7C 0006 115 7E7E 2343 text '#CLOSE' 115 7E80 4C4F 115 7E82 5345 116 7E84 7E86 fclose data $+2 117 7E86 06A0 bl @bank1 117 7E88 8332 118 7E8A 7A10 data _fclos ; see 1-14-File-IO.a99 119 ;] 120 121 ;[ #GET ( buff_addr fid -- t|f ) 122 ; reads a line of input from the file specified by fid. 123 ; The address of an appropriately sized buffer must be supplied. 124 ; If the read is successful, the buffer is filled with the data read from the 125 ; input device, with the first byte being the length count of the data 126 ; immediately following it. 127 ; This can be converted into an address/length pair with COUNT. 128 ; Returns: 129 ; False if successful 130 ; True if not successful 131 ; This allows trapping with ABORT" as follows: 132 ; MYFILE #GET ABORT" Could not read from the file" 133 ; If the read fails, IOERR is set to the error code, otherwise it is zero'd 134 7E8C 7E7A fgeth data fclosh,4 134 7E8E 0004 135 7E90 2347 text '#GET' 135 7E92 4554 136 7E94 7E96 fget data $+2 137 7E96 06A0 bl @bank1 137 7E98 8332 138 7E9A 7A34 data _fget ; see 1-14-File-IO.a99 139 ;] 140 141 ;[ #PUT ( buff_addr len fid - t|f ) 142 ; Places a string from buffer_addr with length len to the file represented by 143 ; fid. 144 ; Returns false if successful, else returns true. 145 ; This can be trapped with ABORT" 146 7E9C 7E8C fputh data fgeth,4 146 7E9E 0004 147 7EA0 2350 text '#PUT' 147 7EA2 5554 148 7EA4 7EA6 fput data $+2 149 7EA6 06A0 bl @bank1 149 7EA8 8332 150 7EAA 7A70 data _fput ; see 1-14-File-IO.a99 151 ;] 152 153 ;[ #REC ( record# fid -- ) 154 ; Sets the record number for reading or writing for relative files 155 7EAC 7E9C frech data fputh,4 155 7EAE 0004 156 7EB0 2352 text '#REC' 156 7EB2 4543 157 7EB4 7EB6 frec data $+2 158 7EB6 06A0 bl @bank1 158 7EB8 8332 159 7EBA 7AE2 data _frec ; see 1-14-File-IO.a99 160 ;] 161 162 ;[ #EOF? ( fid -- t|f ) 163 ; returns true if currently positioned at the end of the file referenced by fid 164 7EBC 7EAC feofh data frech,5 164 7EBE 0005 165 7EC0 2345 text '#EOF? ' 165 7EC2 4F46 165 7EC4 3F20 166 7EC6 7EC8 feof data $+2 167 7EC8 06A0 bl @bank1 167 7ECA 8332 168 7ECC 7AFC data _feof ; see 1-14-File-IO.a99 169 ;] * * COPY 'C:\TI\Source\TurboForth\Bank0\0-20-Sound.a99' * 1 ; _____ _ __ __ _ 2 ; / ____| | | \ \ / / | | 3 ; | (___ ___ _ _ _ __ __| | \ \ /\ / /__ _ __ __| |___ 4 ; \___ \ / _ \| | | | '_ \ / _` | \ \/ \/ / _ \| '__/ _` / __| 5 ; ____) | (_) | |_| | | | | (_| | \ /\ / (_) | | | (_| \__ \ 6 ; |_____/ \___/ \__,_|_| |_|\__,_| \/ \/ \___/|_| \__,_|___/ 7 8 ; SN76489 register writes 9 ; ----------------------- 10 ; When a byte is written to the SN76489, it processes it as follows: 11 ; %1cctdddd 12 ; d=data bits 13 ; t=type bits 14 ; c=channel bits 15 ;If bit 7 is 1 then the byte is a LATCH/DATA byte. 16 ; 17 ; Bits 6 and 5 (cc) give the channel to be latched, ALWAYS. 18 ; This selects the row in the above table. 19 ; %00 is channel 0, %01 is channel 1, %10 is channel 2, %11 is channel 3. 20 ; Bit 4 (t) determines whether to latch volume (1) or tone/noise (0) data. 21 ; The remaining 4 bits (dddd) are placed into the low 4 bits of the relevant 22 ; register. 23 ; For the three-bit noise register, the highest bit is discarded. 24 ; The latched register is NEVER cleared by a data byte. 25 ; If bit 7 is 0 then the byte is a DATA byte. 26 ; 27 ; %0-DDDDDD 28 ; |``````-- Data 29 ; `-------- Unused 30 ; 31 ; If the currently latched register is a tone register then the low 6 bits of 32 ; the byte (DDDDDD) are placed into the high 6 bits of the latched register. 33 ; If the latched register is less than 6 bits wide (ie. not one of the tone 34 ; registers), instead the low bits are placed into the corresponding bits of the 35 ; register, and any extra high bits are discarded. 36 ; The data have the following meanings (described more fully later): 37 ; 38 ; Tone registers 39 ; DDDDDDdddd = cccccccccc 40 ; DDDDDDdddd gives the 10-bit half-wave counter reset value. 41 ; 42 ; Volume registers 43 ; (DDDDDD)dddd = (--vvvv)vvvv 44 ; 45 ; dddd gives the 4-bit volume value. 46 ; If a data byte is written, the low 4 bits of DDDDDD update the 4-bit volume 47 ; value. However, this is unnecessary. 48 ; 49 ; Noise register 50 ; (DDDDDD)dddd = (---trr)-trr 51 ; 52 ; The low 2 bits of dddd select the shift rate and the next highest bit 53 ; (bit 2) selects the mode (white (1) or "periodic" (0)). 54 ; If a data byte is written, its low 3 bits update the shift rate and mode 55 ; in the same way. 56 57 ;[ SOUND ( pitch vol ch# -- ) 58 7ECE 7EBC soundh data feofh,5 58 7ED0 0005 59 7ED2 534F text 'SOUND ' 59 7ED4 554E 59 7ED6 4420 60 7ED8 7EDA sound data $+2 61 7EDA 0207 li r7,>8400 ; address of sound chip 61 7EDC 8400 62 ; set the channel... 63 7EDE C074 mov *stack+,r1 ; pop channel 64 7EE0 C201 mov r1,r8 ; save it 65 7EE2 0200 li r0,>9000 ; set msb and volume latch bit 65 7EE4 9000 66 7EE6 0B31 src r1,3 ; move channel into correct bit position 67 7EE8 E040 soc r0,r1 ; combine 68 ; set the volume... 69 7EEA C034 mov *stack+,r0 ; pop volume 70 7EEC 06C0 swpb r0 ; move to high byte 71 7EEE E040 soc r0,r1 ; combine 72 7EF0 D5C1 movb r1,*r7 ; move to sound chip 73 ; get pitch... 74 7EF2 0241 andi r1,>e000 ; reset t bit (to latch pitch) 74 7EF4 E000 75 7EF6 C034 mov *stack+,r0 ; pop pitch 76 7EF8 C080 mov r0,r2 ; copy it 77 7EFA 0240 andi r0,>000f ; get the low 4 bits 77 7EFC 000F 78 7EFE 06C0 swpb r0 ; move to high byte 79 7F00 E040 soc r0,r1 ; combine 80 7F02 D5C1 movb r1,*r7 ; move to sound chip 81 ; process noise channel if ch#=3... 82 7F04 0288 ci r8,3 ; noise channel? 82 7F06 0003 83 7F08 1302 jeq sndxit ; if so then just exit 84 7F0A 0A42 sla r2,4 ; get upper 6 bits in upper byte 85 7F0C D5C2 movb r2,*r7 ; send to sound chip 86 7F0E 045C sndxit b *next 87 ;] * * COPY 'C:\TI\Source\TurboForth\Bank0\0-21-Editor.a99' * 1 ; ______ _ _ _ __ __ _ 2 ; | ____| | (_) | \ \ / / | | 3 ; | |__ __| |_| |_ ___ _ __ \ \ /\ / /___ _ __ __| |___ 4 ; | __| / _` | | __|/ _ \| '__| \ \/ \/ // _ \| '__/ _` / __| 5 ; | |____| (_| | | |_| (_) | | \ /\ /| (_) | | | (_| \__ \ 6 ; |______|\__,_|_|\__|\___/|_| \/ \/ \___/|_| \__,_|___/ 7 ; block editor 8 9 lastwd ; this is the last word in the built-in dictionary 10 11 ;[ EDIT ( block# -- ) 12 ; loads 'block' and invokes the editor 13 ; on exit from the editor, location TEMP is checked. If not 0, it loads 14 ; the block number in TEMP. 15 7F10 7ECE edith data soundh,4 15 7F12 0004 16 7F14 4544 text 'EDIT' 16 7F16 4954 17 7F18 8320 edit data docol 18 7F1A 61FC data qdup,zbrnch,edit1 ; just exit if block#=0 18 7F1C 65F6 18 7F1E 7F54 19 20 ; if we happen to be in 32 column mode then switch to 40 column mode 21 7F20 77A6 data gxmax ; get xmax 22 7F22 70B2 data lit,32,eq ; is it equal to 32? 22 7F24 0020 22 7F26 647A 23 7F28 65F6 data zbrnch,edit_ ; just continue if not 23 7F2A 7F30 24 7F2C 6084 data lit0,gmode ; otherwise set 40 column mode as default 24 7F2E 795E 25 26 7F30 6D76 edit_ data cls ; clear the screen 27 7F32 6084 data lit0,lit,tib,store ; used as a flag for copy/paste 27 7F34 70B2 27 7F36 3420 27 7F38 6852 28 29 7F3A 7B98 edit0 data block,edit3 ; load block, invoke editor 29 7F3C 7F58 30 31 ; at this point, we have returned from the editor. 32 ; Check if the editor has requested another block... 33 7F3E 70B2 data lit,lstblk,store0 33 7F40 A1B4 33 7F42 6892 34 7F44 70B2 data lit,temp2,fetch,qdup ; get value in temp 34 7F46 A072 34 7F48 6830 34 7F4A 61FC 35 7F4C 65F6 data zbrnch,edit1 ; if 0 just exit 35 7F4E 7F54 36 7F50 65E4 data branch,edit0 ; otherwise, load next block 36 7F52 7F3A 37 38 7F54 6D76 edit1 data cls,exit ; clear screen and exit 38 7F56 832C 39 40 7F58 7F5A edit3 data $+2 41 7F5A 06A0 bl @bank1 41 7F5C 8332 42 7F5E 6EA2 data _edit ; see 1-11-Editor.a99 43 ;] * * COPY 'C:\TI\Source\TurboForth\Bank0\0-22-VDP.a99' * 1 ; __ _______ _____ _ _ _ _ _ _ _ _ 2 ; \ \ / / __ \| __ \ | | | | | (_) (_) | (_) 3 ; \ \ / /| | | | |__) | | | | | |_ _| |_| |_ _ ___ ___ 4 ; \ \/ / | | | | ___/ | | | | __| | | | __| |/ _ | __| 5 ; \ / | |__| | | | |__| | |_| | | | |_| | __|__ \ 6 ; \/ |_____/|_| \____/ \__|_|_|_|\__|_|\___|___/ 7 ; VDP access utility routines 8 9 ;[ VDP addresses: 10 0000 83D7 vblnk equ >83D7 ; vertical blank counter 11 0000 8800 vdpr equ >8800 ; vdp read register 12 0000 8C00 vdpw equ >8C00 ; vdp write register 13 0000 8C02 vdpa equ >8C02 ; vdp address register 14 ;] 15 16 ; bit1 data >4000 ; used for re-setting bit 1 17 ; note: bit1 is now defined in LFREE in 0-07-Memory.a99 18 19 ;[ vdp single byte read 20 ; inputs: r0=address in vdp to read, r1(msb), the byte read from vdp 21 ; side effects: none 22 7F60 C820 vsbr mov @bank0,@retbnk ; return to bank 0 if interrupt should trigger 22 7F62 606A 22 7F64 A06E 23 7F66 0300 limi 2 ; briefly enable interrupts 23 7F68 0002 24 7F6A 0300 limi 0 ; and switch 'em off again 24 7F6C 0000 25 7F6E 06C0 swpb r0 ; get low byte of address 26 7F70 D800 movb r0,@vdpa ; write it to vdp address register 26 7F72 8C02 27 7F74 06C0 swpb r0 ; get high byte 28 7F76 D800 movb r0,@vdpa ; write 28 7F78 8C02 29 7F7A 1000 nop 30 7F7C D060 movb @vdpr,r1 ; write payload 30 7F7E 8800 31 7F80 045B rt ; see ya 32 ;] 33 34 ;[ vdp multiple byte read 35 ; inputs: r0=vdp source address, r1=cpu ram destination address 36 ; r2=number of bytes to read 37 ; side effects: r1 & r2 changed 38 7F82 06C0 vmbr swpb r0 ; get low byte of address 39 7F84 D800 movb r0,@vdpa ; write it 39 7F86 8C02 40 7F88 06C0 swpb r0 ; get high byte of address 41 7F8A D800 movb r0,@vdpa ; write it 41 7F8C 8C02 42 7F8E 020F li r15,vdpr ; cache vdp write register address in r15 42 7F90 8800 43 7F92 DC5F vmbr1 movb *r15,*r1+ ; fast write to vdp register 44 7F94 0602 dec r2 ; finished? 45 7F96 16FD jne vmbr1 ; loop if not 46 7F98 045B rt ; so long 47 ;] 48 49 ;[ vdp single byte write 50 ; inputs: r0=address in vdp to write to, r1(msb)=the byte to write 51 ; side effects: none 52 7F9A C820 vsbw mov @bank0,@retbnk ; return to bank 0 if interrupt should trigger 52 7F9C 606A 52 7F9E A06E 53 7FA0 0300 limi 2 ; briefly enable interrupts 53 7FA2 0002 54 7FA4 0300 limi 0 ; but too long, we're British you know 54 7FA6 0000 55 7FA8 0260 vsbw0 ori r0,>4000 ; tell VDP processor "hey, this is a *write*" 55 7FAA 4000 56 7FAC 06C0 swpb r0 ; get low byte of address 57 7FAE D800 movb r0,@vdpa ; write it to vdp address register 57 7FB0 8C02 58 7FB2 06C0 swpb r0 ; get high byte of address 59 7FB4 D800 movb r0,@vdpa ; write it 59 7FB6 8C02 60 7FB8 D801 movb r1,@vdpw ; write payload 60 7FBA 8C00 61 7FBC 2820 xor @bit1,r0 ; reset bit 1 61 7FBE 695E 62 7FC0 045B rt ; we'd love to stay, but we have a long drive... 63 ;] 64 65 ;[ vdp multiple byte write 66 ; r0=destination in vdp, r1=source address in cpu ram, r2=number of bytes 67 ; side effects: r1 & r2 changed 68 7FC2 C820 vmbw mov @bank0,@retbnk ; return to bank 0 if interrupt should trigger 68 7FC4 606A 68 7FC6 A06E 69 7FC8 0300 limi 2 ; briefly enable interrupts 69 7FCA 0002 70 7FCC 0300 limi 0 ; this is getting boring now 70 7FCE 0000 71 7FD0 0260 vmbw0 ori r0,>4000 ; if you can't figure this out by now 71 7FD2 4000 72 7FD4 06C0 swpb r0 ; then try the Commodore 64 73 7FD6 D800 movb r0,@vdpa ; it's a much inferior machine 73 7FD8 8C02 74 7FDA 06C0 swpb r0 ; with the worlds worst processor 75 7FDC D800 movb r0,@vdpa ; though Chuck Peddle is extremely cool 75 7FDE 8C02 76 7FE0 020F li r15,vdpw ; and you have to hand it to Jack Tramiel too. 76 7FE2 8C00 77 7FE4 D7F1 vmbw1 movb *r1+,*r15 ; Anyway the C64 has much simpler hardware 78 7FE6 0602 dec r2 ; and a super simple (i.e. super sucky) CPU 79 7FE8 16FD jne vmbw1 ; but hey, it *does* have 64K of ram, the lucky 80 7FEA 2820 xor @bit1,r0 ; old git. 80 7FEC 695E 81 7FEE 045B rt ; been nice chatting with ya... 82 ;] * * COPY 'C:\TI\Source\TurboForth\Bank0\0-23-System.a99' * 1 ; ____ __ __ _ 2 ; | _ \ / _|/ _| | | 3 ; | |_) |_ _| |_| |_ ___ _ __ ___ __ _ _ __ __| | 4 ; | _ <| | | | _| _/ _ \ '__/ __| / _` | '_ \ / _` | 5 ; | |_) | |_| | | | || __/ | \__ \ | (_| | | | | (_| | 6 ; |____/ \__,_|_| |_| \___|_| |___/ \__,_|_| |_|\__,_| 7 ; __ __ _ _ _ 8 ; \ \ / / (_) | | | | 9 ; \ \ / /__ _ _ __ _ __ _| |__ | | ___ ___ 10 ; \ \/ // _` | '__| |/ _` | '_ \| |/ _ | __| 11 ; \ /| (_| | | | | (_| | |_) | | __|__ \ 12 ; \/ \__,_|_| |_|\__,_|_.__/|_|\___|___/ 13 14 0000 7FF0 endB0 equ $ ; end of bank 0 marker 15 16 dorg >a000 17 ; note: during initialisation, GPLLNK uses >A000 to >A01F as workspace 18 ; to load the upper case characters from console GROM. After this, 19 ; the space is re-used. 20 21 ;[ Vectors - the locations of these vectors MUST NOT change between builds 22 A000 0000 intvec bss 2 ; vector for INTERPRET >a000 23 A002 0000 blkvec bss 2 ; vector for BLOCK >a002 24 A004 0000 numvec bss 2 ; vector for NUMBER >a004 25 A006 0000 fndvec bss 2 ; vector for FIND >a006 26 A008 0000 usrisr bss 2 ; vector for user isr >a008 27 A00A 0000 _wwrap bss 2 ; word-wrap on/off >a00a 28 A00C 0000 dsrvec bss 2 ; pointer to DSRLNK vector in bank 1 >a00c 29 A00E 0000 gplvec bss 2 ; pointer to GPLLNK vector in bank 1 >a00e 30 A010 0000 padvec bss 2 ; pointer to scratchpad restore code in bank 1. >a010 31 ; Assembly language vector for returning to TF from external assembly code 32 ; that runs in a different workspace. 33 ; External assembly code (for example, code written with the TF assembler) 34 ; that changes workspace can simply perform a BLWP @>A012 to restore TF's 35 ; workspace and jump to NEXT in the inner interpreter, which will restore 36 ; normal Forth execution perfectly. 37 A012 0000 wp bss 2 ; >a012 - workspace pointer. 38 ; software can actually change TF's workspace while running. 39 ; a copy of the desired workspace address MUST be written 40 ; here so that KEY can restore the correct workspace address 41 ; after its call into the TI ROM. 42 43 A014 0000 pnext bss 2 ; >a014 pointer to next 44 A016 0000 pdocon bss 2 ; >a016 pointer to DOCON's executable code 45 A018 0000 pcreate bss 2 ; >a018 pointer to CREATE's executable code 46 ; new vectors MUST be added here 47 ;] 48 49 ;[ memory space pointers 50 A01A 0000 ffailm bss 2 ; >a01a first free address in low memory pointer 51 A01C 0000 ffaihm bss 2 ; >a01c first free address in hi memory pointer 52 ;] 53 54 ;[ stack pointers 55 A01E 0000 s0 bss 2 ; reserved for FORTH variable S0 - holds the address of the 56 ; start of the data stack (r4) 57 58 A020 0000 rs0 bss 2 ; address of start of return stack (r5) 59 ;] 60 61 ;[ screen, keyboard and file I/O 62 A022 0000 keydev bss 2 ; keyboard device to use for KSCAN routine in console ROM 63 A024 0000 cursrd bss 2 ; cursor delay used in KEY and the editor 64 A026 0000 noscrl bss 2 ; suppress screen scrolling. >0=suppress 65 A028 0000 scrX bss 2 ; x co-ordinate of next character to be displayed on screen 66 A02A 0000 scrY bss 2 ; y co-ordinate of next character to be displayed on screen 67 A02C 0000 xmax bss 2 ; screen width - 32, 40 or 80 68 A02E 0000 ymax bss 2 ; screen height - always 24 69 A030 0000 wrap bss 2 ; used to determine if wrap-around is used by SCROLL 70 A032 0000 panxy bss 2 ; starting screen address (top left) of panel 71 A034 0000 panr bss 2 ; number of rows in panel 72 A036 0000 panc bss 2 ; number of columns in panel 73 A038 0000 errnum bss 2 ; holds io error number of last error 74 ;] 75 76 ;[ speech synthesis 77 A03A 0000 spcnt bss 2 ; number of bytes remaining in speech buffer 78 A03C 0000 spadr bss 2 ; address of next byte in speech buffer 79 A03E 0000 spcsvc bss 2 ; speech service: address of the speech service which should 80 ; be called by the ISR is placed here. (either the routine 81 ; to stream raw speech data, or the routine to feed speech 82 ; ROM addresses). 83 84 A040 0000 synyes bss 2 ; 0=speech synth not fitted. >FFFF=speech synth detected 85 ;] 86 87 ;[ parsing/compilation 88 A042 0000 in bss 2 ; holds the current index into the terminal input buffer 89 ; (TIB) - used by variable >IN 90 91 A044 0000 latest bss 2 ; reserved for FORTH variable LATEST, which points to the 92 ; most recently defined word in the dictionary. 93 94 A046 0000 here bss 2 ; points to the next free byte of memory. When compiling, 95 ; compiled words go HERE. 96 97 A048 0000 _state bss 2 ; is the interpreter interpreting (0) or compiling a word 98 ; (!=0). 99 100 A04A 0000 tibsiz bss 2 ; characters per line: 80 on command line, 64 in blocks 101 A04C 0000 _span bss 2 ; the number of characters received by EXPECT. 102 ; See variable #TIB. 103 104 A04E 0000 doboot bss 2 ; "we're booting" flag (>0=booting) 105 A050 0000 sdelim bss 2 ; stores the end of string marker (normally ") for S". 106 ; the word .( sets it temporarily to a ) character. 107 108 A052 0000 isdbl bss 2 ; flag to indicate if NUMBER pushed a double (>0=yes) 109 A054 0000 dpl bss 2 ; decimal point location. set by NUMBER (doubles only) 110 A056 0000 cassen bss 2 ; if 0 dictionary searches are case sensitive 111 A058 0000 source bss 2 ; source-id. -1=string (via evaluate). 112 ; 0=user input (keyboard/block). 113 114 A05A 0000 dotsin bss 2 ; flag for .S to use signed or unsigned numbers 115 A05C 0000 base bss 2 ; the current base for printing and reading numbers 116 A05E 0000 lbase bss 2 ; last number base, used by Number to String routine 117 A060 0000 expcnt bss 2 ; exponent count, used by Number to String routine 118 A062 0000 lzi bss 2 ; leading zero indicator, used by N>S routine to determine 119 ; if leading 0's are ignored. 120 121 A064 0000 dosign bss 2 ; flag for NTS routine. If >0, then NTS will treat numbers 122 ; as unsigned, set by U. and . 123 124 A066 0000 _warn bss 2 ; redefinition warnings are suppressed if _warn=0 125 A068 0000 coding bss 2 ; !0 if CODE: compiling is active 126 A06A 0000 patch bss 2 ; holds the CFA of latest word created with CREATE in case 127 ; DOES> needs to patch it 128 ;] 129 130 ;[ misc 131 A06C 0000 vdpr1 bss 2 ; copy of vdp register 1 (stored at 83d4) 132 A06E 0000 retbnk bss 2 ; holds bank number to return to as a memory address 133 ; (>6000 or >6002) 134 A070 0000 temp bss 2 ; for temporary storage 135 A072 0000 temp2 bss 2 ; for temporary storage 136 A074 0000 temp3 bss 2 ; for temporary storage 137 A076 0000 seed bss 2 ; seed for random number generation 138 A078 0000 sumode bss 2 ; graphics mode selected from cartridge menu screen 139 ;] 140 141 ;[ editor variables - only used by the built in editor 142 A07A 0000 epage bss 2 ; holds block editor page 143 ; note: These variables use the same addresses as the compiler reference 144 ; counters (below). This is safe to do, as the compiler is never in use when 145 ; the editor is in use, and vice versa. Hence it makes sense to use the same 146 ; addresses and save some valuable user RAM in low-memory. I'm nice like that. 147 0000 A07C csrx equ $ ; cursor x for editor 148 0000 A07E csry equ $+2 ; cursor y for editor 149 0000 A080 csrflg equ $+4 ; cursor blink flag for editor 150 0000 A082 autorp equ $+6 ; keyboard auto repeat counter 151 0000 A084 autorl equ $+8 ; keyboard auto repeat re-load value 152 0000 A086 edblk equ $+10 ; block number of the block currently being edited 153 ;] 154 155 ;[ reference counters for compiler security 156 ; see the words : and ; in 0-10-Compilation.a99 157 A07C 0000 ifcnt bss 2 ; incremented by IF, decremented by THEN 158 A07E 0000 docnt bss 2 ; incremented by DO, decremented by LOOP & +LOOP 159 A080 0000 forcnt bss 2 ; incremented by FOR, decremented by NEXT 160 A082 0000 cascnt bss 2 ; incremented by CASE, decremented by ENDCASE 161 A084 0000 ofcnt bss 2 ; incremented by OF, decremented by ENDOF 162 A086 0000 begcnt bss 2 ; incremented by BEGIN, decremented by UNTIL, REPEAT & AGAIN 163 ;] 164 165 ;[ sprite buffers 166 A088 0000 sal bss 128 ; sprite attribute list 167 A108 0000 smlist bss 64 ; sprite movement list 168 ;] 169 170 ;[ Persistable data for file IO 171 A148 0000 sav8a bss 2 ; save data following blwp @dsrlnk (8 or >a) 172 A14A 0000 savcru bss 2 ; cru address of the peripheral 173 A14C 0000 savent bss 2 ; entry address of dsr or subprogram 174 A14E 0000 savlen bss 2 ; device or subprogram name length 175 A150 0000 savpab bss 2 ; pointer to device or subprogram in the pab 176 A152 0000 savver bss 2 ; version # of dsr 177 A154 0000 flgptr bss 2 ; pointer to flag in pab (byte 1 in pab) 178 A156 0000 dsrlws bss 10 ; data 0,0,0,0,0 ; dsrlnk workspace 179 A160 0000 dstype bss 22 ; data 0,0,0,0,0,0,0,0,0,0,0 180 A176 0000 haa bss 2 ; used to store AA pattern for DSR ROM detection 181 A178 0000 namsto bss 8 ; dsrlnk 8 bytes device name buffer 182 ;] 183 184 ;[ scratch pab - used for block IO 185 A180 00 pabopc byte 0 ; opcode: open, read, etc 186 A181 00 pabflg byte 0 ; error code & file type 187 A182 0000 pabbuf data 0 ; vdp address of data 188 A184 00 pablrl byte 0 ; logical record length 189 A185 00 pabcc byte 0 ; output character count 190 A186 0000 pabrec data 0 ; record number 191 A188 00 pabsco byte 0 ; screen offset for char 192 A189 00 pabnln byte 0 ; name length 193 A18A 0000 pabfil bss 32 ; file name starts here 194 even 195 ;] 196 197 ;[ set up the pab pointers: 198 0000 8356 namptr equ >8356 ; address of pointer to name length in PABs 199 0000 1800 f1pab equ >1800 ; vdp address of 40 byte PAB buffer for file 1 200 0000 1828 f1buf equ >1828 ; vdp address of 256 byte record buffer for file 1 201 0000 1928 f2pab equ >1928 ; vdp address of 40 byte PAB buffer for file 2 202 0000 1950 f2buf equ >1950 ; vdp address of 256 byte record buffer for file 2 203 0000 1A50 f3pab equ >1a50 ; vdp address of 40 byte PAB buffer for file 3 204 0000 1A78 f3buf equ >1a78 ; vdp address of 256 byte record buffer for file 3 205 0000 1B78 pabloc equ >1b78 ; vdp address of block IO PAB 206 0000 1BA0 recbuf equ >1ba0 ; vdp address of data buffer. 128 bytes to store 1 record 207 0000 1C20 bufadd equ >1c20 ; vdp address of block buffer 0 208 209 A1AA 0000 falloc bss 6 ; allocation table for file IO 210 ; at run time, these 3 words are filled with addresses f1pab, f2pab & f3pab. 211 ; The MSB is set when a file is in use (i.e. when opened with #OPEN). 212 ; The MSB is reset when #CLOSE is executed, and thus the file 'slot' can be 213 ; re-used. 214 ;] 215 216 ;[ block related data 217 ; see 0-18-Blocks.a99 218 0000 0006 blocks equ 6 ; number of block buffers 219 A1B0 0000 totblk bss 2 ; number of block buffers available 220 A1B2 0000 blknum bss 2 ; holds the block currently being compiled by INTERPRET 221 A1B4 0000 lstblk bss 2 ; holds the block currently being worked on 222 A1B6 0000 blk0 bss 2 ; block number of the block stored in buf0 (0=unassigned) 223 A1B8 0000 bss 2 ; VDP address of block0 MSB=1=dirty block 224 A1BA 0000 blk1 bss 2 ; block number of the block stored in buf1 (0=unassigned) 225 A1BC 0000 bss 2 ; VDP address of block1 MSB=1=dirty block 226 A1BE 0000 blk2 bss 2 ; block number of the block stored in buf2 (0=unassigned) 227 A1C0 0000 bss 2 ; VDP address of block2 MSB=1=dirty block 228 A1C2 0000 blk3 bss 2 ; block number of the block stored in buf3 (0=unassigned) 229 A1C4 0000 bss 2 ; VDP address of block3 MSB=1=dirty block 230 A1C6 0000 blk4 bss 2 ; block number of the block stored in buf4 (0=unassigned) 231 A1C8 0000 bss 2 ; VDP address of block4 MSB=1=dirty block 232 A1CA 0000 blk5 bss 2 ; block number of the block stored in buf5 (0=unassigned) 233 A1CC 0000 bss 2 ; VDP address of block5 MSB=1=dirty block 234 ; note: the vdp addresses of the block buffers are defined in 235 ; 1-15-Initialise.a99 236 ;] 237 238 ;[ stacks and buffers 239 ; don't change the order of these buffers! 240 A1CE 0000 tibadr bss 2 ; address of the terminal input buffer 241 0000 3420 tib equ >3420 ; vdp address of terminal input buffer 242 A1D0 0000 wrdbuf bss 82 243 A222 0000 wrkbuf bss 32 ; work buffer for Number to String routine (holds exponents) 244 A242 0000 strbuf bss 18 ; string buffer for Number to String routine to construct 245 ; a string in 246 ;] 247 248 ;[ data stack and return stack 249 A254 0000 stacks bss 114 ; reserve space for data stack and return stack 250 0000 A28A retstk equ stacks+54 ; return stack grows to lower addresses 251 0000 A2C6 dstack equ $ ; data stack grows to lower addresses 252 ;] 253 254 ;[ start of user memory... FORTH programs go here! 255 0000 A2C6 himem equ $ ; first free address in hi memory 256 0000 A2C6 prgtop equ himem ; program space - user defined FORTH words start here 257 ; at startup, HERE points to prgtop 258 ;] * * COPY 'C:\TI\Source\TurboForth\Bank1\1-00-Header.a99' * 1 ; _____ _ _____ _ _ 2 ; |_ _|_ _ _ __| |__ ___ | ___|___ _ __| |_| |__ 3 ; | | | | | | '__| '_ \ / _ \| |_ / _ \| '__| __| '_ \ 4 ; | | | |_| | | | |_) | (_) | _|| (_) | | | |_| | | | 5 ; |_| \__,_|_| |_.__/ \___/|_| \___/|_| \__|_| |_| 6 ; ################################################ 7 ; TurboForth 8 ; (C) Mark Wills 2010-2012 9 ; Written in TMS9900 machine code for the TI-99/4A 10 ; May the Forth be with you. 11 ; ################################################ 12 ; ____ _ _ 13 ; | __ ) __ _ _ __ | | __ / | 14 ; | _ \ / _` | '_ \| |/ / | | 15 ; | |_) | (_| | | | | < | | 16 ; |____/ \__,_|_| |_|_|\_\ |_| 17 ; 18 ; This is bank 1 - the secondary bank 19 ; This bank consists of subroutines called by bank 0 20 ; 21 ; Cartridge header. Unfortunatley, we cannot know for sure that the 22 ; correct bank will be selected at power-up, thus we need to duplicate 23 ; the cartridge header here. This header is slightly different however, 24 ; it copies a simple bootstrap routine to pad ram which selects bank 0 25 ; and then jumps to the real bootstrap code in bank 0 26 27 aorg >6000 ; cartridge rom 28 29 ; cartridge ROM header 30 31 6000 AA byte >aa ; standard header 32 6001 0C byte >0c ; version number 33 6002 01 byte >01 ; number of programs 34 6003 00 byte >00 ; not used 35 6004 0000 data >0000 ; pointer to power-up list 36 6006 600C data menu ; pointer to program list 37 6008 0000 data 0 ; pointer to DSRL list 38 600A 0000 data 0 ; pointer to subprogram list 39 40 600C 6026 data menu40 ; pointer to next menu item 41 600E 605C data start80 ; code entry point 42 6010 14 byte 20 ; length of text 43 6011 5455 text 'TURBOFORTH 80 COLUMN' 43 6013 5242 43 6015 4F46 43 6017 4F52 43 6019 5448 43 601B 2038 43 601D 3020 43 601F 434F 43 6021 4C55 43 6023 4D4E 44 6025 0000 even 45 6026 0000 data 0 ; no more menu entries 46 6028 6052 data start40 ; code entry point (see below) 47 602A 11 byte 17 ; length of text 48 602B 5455 text 'TURBOFORTH V1.2.1:1 (c) 2015 Mark Wills' 48 602D 5242 48 602F 4F46 48 6031 4F52 48 6033 5448 48 6035 2056 48 6037 312E 48 6039 322E 48 603B 313A 48 603D 3120 48 603F 2863 48 6041 2920 48 6043 3230 48 6045 3135 48 6047 204D 48 6049 6172 48 604B 6B20 48 604D 5769 48 604F 6C6C 48 6051 73 49 even 50 51 ; 40 column mode entry point 52 6052 02E0 lwpi wkspc 52 6054 8300 53 6056 04E0 clr @sumode 53 6058 A078 54 605A 1009 jmp startB1 55 56 ; 80 column mode entry point 57 605C 02E0 lwpi wkspc 57 605E 8300 58 6060 0200 li r0,2 58 6062 0002 59 6064 C800 mov r0,@sumode 59 6066 A078 60 6068 1002 jmp startB1 61 62 ; codes for bank 0 and bank 1 - used by the interrupt handler to determine 63 ; which bank to return to after processing an interrupt. 64 ; Set by the VDP routines (see 0-21-VDP.a99). 65 ; DO NOT MOVE THESE! Identical definitions are made in bank 0, and they MUST 66 ; be at identical addresses! 67 606A 6002 data >6002 ; code to select bank 0 68 606C 6000 data >6000 ; code to select bank 1 69 70 71 606E 0300 startB1 limi 0 ; no interrupts - we're British 71 6070 0000 72 6072 04E0 clr @>6000 ; select bank1 72 6074 6000 73 6076 0460 b @init ; init is defined in 1-15-Initialise.a99 73 6078 7B76 * * COPY 'C:\TI\Source\TurboForth\Bank1\1-01-ISR.a99' * 1 ; _____ _ _ 2 ; |_ _| | | | | 3 ; | | _ __ | |_ ___ _ __ _ __ _ _ _ __ | |_ 4 ; | | | '_ \| __|/ _ \ '__| '__| | | | '_ \| __| 5 ; _| |_| | | | |_| __/ | | | | |_| | |_) | |_ 6 ; |_____|_| |_|\__|\___|_| |_| \__,_| .__/ \__| 7 ; | | 8 ; |_| 9 ; _____ _ _ 10 ; | __ \ | | | | 11 ; | | | | ___ ___ _ __ __ _| |_ ___| |__ ___ _ __ 12 ; | | | |/ _ | __| '_ \ / _` | __|/ __| '_ \ / _ \ '__| 13 ; | |__| | __|__ \ |_) | (_| | |_| (__| | | | __/ | 14 ; |_____/ \___|___/ .__/ \__,_|\__|\___|_| |_|\___|_| 15 ; | | 16 ; |_| 17 ; ISR despatcher - determines which ISR to call 18 ; Speech is serviced every frame, sprites and music are serviced every alternate 19 ; frame. 20 21 607A C28B isrdes mov r11,r10 ; save return address to pad isr 22 23 ; Speech Handling ISR 24 ; Called every frame 25 ; Checks to see if there is any speech to process, if not, just exits 26 ; If there is, either calls ROMSPK to speak words from the speech ROM or calls 27 ; STRSPK to send a raw byte stream to the synth, depending on the address loaded 28 ; into SPCSVC. 29 ; 30 ; First service any speech that is waiting to be sent to the speech synth 31 ; if no speech is outstanding then exit the isr completely... 32 607C C020 speech mov @spcsvc,r0 ; get speech service address in r0 32 607E A03E 33 6080 1301 jeq isrnxt ; if 0 then there is no speech to process so 34 6082 0450 b *r0 ; exit otherwise jump to the routine 35 36 ; check user isr 37 6084 C020 isrnxt mov @usrisr,r0 ; get user interrupt service routine address 37 6086 A008 38 6088 1301 jeq isrout ; if zero then quit isr processing 39 608A 0690 bl *r0 ; otherwise branch and link to user ISR 40 ; (user ISR code should execute an RT to 41 ; return here) 42 43 608C 0460 isrout b @isrxit ; return to Forth environment 43 608E 8354 44 45 ; ------------------------------------------------------------------------------ 46 47 0000 0008 refill equ 8 ; # of bytes to refill the synth fifo with 48 ;[ 'stream-speak' routine to feed raw speech bytes to the speech synth 49 strspk 50 ; if speech synth is already busy then just exit, we'll start up proper 51 ; when the synth is idle... 52 6090 06A0 bl @spstat ; get speech synth status 52 6092 8340 53 6094 C020 mov @spdata,r0 ; get the status from pad ram 53 6096 834A 54 6098 0240 andi r0,>8000 ; check busy flag 54 609A 8000 55 609C 162A jne strxit ; exit if busy 56 ; speech unit is idle... fill fifo with 16 bytes of speech data... 57 609E C020 mov @spadr,r0 ; address of speech data 57 60A0 A03C 58 60A2 0202 li r2,16 ; 16 bytes to fill the fifo 58 60A4 0010 59 60A6 D830 strsp2 movb *r0+,@spchwt ; write a byte to the speech synth 59 60A8 9400 60 60AA 0602 dec r2 ; decrement loop counter 61 60AC 16FC jne strsp2 ; loop if not finished 62 60AE 0201 li r1,-16 ; reduce bytes remaining by 16 62 60B0 FFF0 63 60B2 A801 a r1,@spcnt ; store it 63 60B4 A03A 64 60B6 C800 mov r0,@spadr ; store address of data 64 60B8 A03C 65 60BA 0200 li r0,strsp3 ; new entry point for the next interrupt 65 60BC 60C4 66 60BE C800 mov r0,@spcsvc ; load it 66 60C0 A03E 67 60C2 1017 jmp strxit ; quit. we'll enter at STRSP3 on the next 68 ; interrupt 69 ; check fifo level. If fifo low, stream 8 bytes (or until data is exhausted) 70 ; to the fifo 71 60C4 06A0 strsp3 bl @spstat ; get synth status 71 60C6 8340 72 60C8 C020 mov @spdata,r0 ; move status from pad ram 72 60CA 834A 73 60CC 0240 andi r0,>4000 ; check fifo low bit 73 60CE 4000 74 60D0 1310 jeq strxit ; if not on, then exit - fifo doesn't need 75 ; filling 76 60D2 C020 mov @spadr,r0 ; buffer address 76 60D4 A03C 77 60D6 C060 mov @spcnt,r1 ; bytes remaining 77 60D8 A03A 78 60DA 0202 li r2,refill ; 'refill' bytes to stream 78 60DC 0008 79 60DE D830 strnb movb *r0+,@spchwt ; send a byte to the fifo 79 60E0 9400 80 60E2 0601 dec r1 ; decrement bytes remaining count 81 60E4 1307 jeq strcu ; if all data exhausted then clean up 82 60E6 0602 dec r2 ; decrement counter 83 60E8 16FA jne strnb ; do next byte if not finished 84 60EA C800 mov r0,@spadr ; store address 84 60EC A03C 85 60EE C801 mov r1,@spcnt ; store count 85 60F0 A03A 86 60F2 10C8 strxit jmp isrnxt ; go check user isr 87 ; we've streamed all the data, clean up and exit 88 60F4 04E0 strcu clr @spcsvc ; clear speech service pointer - we're done 88 60F6 A03E 89 60F8 10C5 jmp isrnxt ; go check user isr 90 ;] 91 92 ;[ 'rom-speak' routine to feed rom addresses to the speech synth 93 romspk ; check speech synth, exit if synth is busy... 94 60FA 06A0 bl @spstat ; get status from speech synth into 94 60FC 8340 95 ; scratch-pad ram 96 60FE C020 mov @spdata,r0 ; get the data from speech synth 96 6100 834A 97 6102 0240 andi r0,>8000 ; speech synth busy? 97 6104 8000 98 6106 1613 jne romspx ; exit if busy 99 ; speech synth isn't busy... send a word of data... 100 6108 C060 mov @spadr,r1 ; get address of data word 100 610A A03C 101 610C C031 mov *r1+,r0 ; get the word in r0 for spaddr 102 610E C801 mov r1,@spadr ; update buffer address 102 6110 A03C 103 ; convert the address to nybbles and send to the speech synth... 104 6112 06A0 bl @spaddr ; load the address contained in r0 104 6114 66B2 105 ; 42uS delay required before the 'talk' command can be issued to the speech 106 ; synth. see editor/assembler manual, section 22.1.1, page 349 107 6116 0200 li r0,20 107 6118 0014 108 611A 0600 dly42 dec r0 ; spin the wheels... 109 611C 16FE jne dly42 110 ; send 'talk from rom' opcode to speech synth to make the synth actually 111 ; talk... 112 611E D820 movb @spkROM,@spchwt ; send 'speak from rom op-code' 112 6120 662A 112 6122 9400 113 ; synth is now talking 114 ; do isr housekeeping... 115 6124 0620 dec @spcnt ; decrement 'speech data remaining' counter 115 6126 A03A 116 6128 1602 jne romspx ; if not zero then just exit 117 612A 04E0 clr @spcsvc ; otherwise clear speech-service-routine 117 612C A03E 118 ; pointer since there is no more data to 119 ; service. 120 612E 0460 romspx b @isrxit ; return to next stage of isr handler 120 6130 8354 121 ; (in 1-15-initialise.a99) 122 ;] 123 ; end of speech ISR 124 ; ----------------------------------------------------------------------------- * * COPY 'C:\TI\Source\TurboForth\Bank1\1-02-Console.a99' * 1 ; _____ _ __ __ _ 2 ; / ____| | | \ \ / / | | 3 ; | | ___ _ __ ___ ___ | | ___ \ \ /\ / /___ _ __ __| |___ 4 ; | | / _ \| '_ \/ __|/ _ \| |/ _ \ \ \/ \/ // _ \| '__/ _` / __| 5 ; | |____| (_) | | | \__ \ (_) | | __/ \ /\ /| (_) | | | (_| \__ \ 6 ; \_____|\___/|_| |_|___/\___/|_|\___| \/ \/ \___/|_| \__,_|___/ 7 ; Console IO words 8 9 ;[ PAGE ( -- ) see 0-09-Console.a99 10 6132 06A0 _cls bl @cls_ ; Forth word entry point 10 6134 613A 11 6136 0460 b @retB0 11 6138 833A 12 ; entry point if called as assembler subroutine: 13 613A C18B cls_ mov r11,r6 ; save return address 14 613C C060 mov @xmax,r1 ; calculate the character count 14 613E A02C 15 6140 0200 li r0,24 ; according to the... 15 6142 0018 16 6144 3840 mpy r0,r1 ; ...text mode 17 6146 04C0 clr r0 ; screen address 18 6148 0201 li r1,>2000 ; space character 18 614A 2000 19 614C 06A0 bl @vsbwmi ; wipe screen 19 614E 7880 20 6150 04E0 clr @scrX ; zero x coordinate 20 6152 A028 21 6154 04E0 clr @scrY ; zero y coordinate 21 6156 A02A 22 6158 0456 b *r6 ; return to caller 23 ;] 24 25 ;[ JOYST ( joystick# -- value ) 26 ; Scans the joystick returning the direction value 27 615A C054 _joyst mov *stack,r1 ; get unit number 28 615C 0221 ai r1,6 ; use keyboard select 6 for #0, 7 for #1 28 615E 0006 29 6160 06C1 swpb r1 30 6162 020C li r12,36 30 6164 0024 31 6166 30C1 ldcr r1,3 32 6168 020C li r12,6 32 616A 0006 33 616C 3541 stcr r1,5 34 616E 06C1 swpb r1 35 6170 0541 inv r1 36 6172 0241 andi r1,>001f 36 6174 001F 37 6176 C501 mov r1,*stack 38 6178 020C li r12,_next 38 617A 8326 39 617C C80C mov r12,@>83d6 ; defeat auto screen blanking 39 617E 83D6 40 6180 C820 mov @bank1_,@retbnk ; return to bank 1 if interuupts should fire 40 6182 606C 40 6184 A06E 41 6186 0300 limi 2 ; briefly enable interrupts 41 6188 0002 42 618A 0300 limi 0 ; and turn 'em off again 42 618C 0000 43 618E 0460 b @retb0 ; return to caller in bank 0 43 6190 833A 44 ;] 45 46 * * COPY 'C:\TI\Source\TurboForth\Bank1\1-03-Graphics.a99' * 1 ; _____ _ _ __ __ _ 2 ; / ____| | | (_) \ \ / / | | 3 ; | | __ _ __ __ _ _ __ | |__ _ ___ ___ \ \ /\ / /___ _ __ __| |___ 4 ; | | |_ | '__/ _` | '_ \| '_ \| |/ __/ __| \ \/ \/ // _ \| '__/ _` / __| 5 ; | |__| | | | (_| | |_) | | | | | (__\__ \ \ /\ /| (_) | | | (_| \__ \ 6 ; \_____|_| \__,_| .__/|_| |_|_|\___|___/ \/ \/ \___/|_| \__,_|___/ 7 ; | | 8 ; |_| 9 ; graphics related commands 10 11 ;[ GMODE ( gmode -- ) 12 6192 C234 _gmode mov *stack+,r8 ; pop gmode 13 6194 0288 ci r8,0 ; 40 column mode? 13 6196 0000 14 6198 1306 jeq s40col ; jump if yes 15 619A 0288 ci r8,1 ; 32 column mode? 15 619C 0001 16 619E 1306 jeq s32col ; jump if yes 17 61A0 0288 ci r8,2 ; 80 column mode? 17 61A2 0002 18 61A4 1306 jeq s80col ; jump if yes 19 ; otherwise illegal graphics mode selected, 20 ; so fall through to 40 column mode... 21 61A6 0202 s40col li r2,col40d ; vdp register data for 40 column mode 21 61A8 622A 22 61AA 1005 jmp ldvdpr ; go load the vdp registers 23 61AC 0202 s32col li r2,col32d ; vdp register data for 32 column mode 23 61AE 6234 24 61B0 1002 jmp ldvdpr ; go load the vdp registers 25 61B2 0202 s80col li r2,col80d ; vdp register data for 80 column mode 25 61B4 623E 26 ; load the vdp registers 27 61B6 C1C2 ldvdpr mov r2,r7 ; save address for later 28 61B8 D072 movb *r2+,r1 ; number of registers to load 29 61BA 0881 sra r1,8 ; move the count to the low byte 30 61BC 04C0 clr r0 ; start with register 0 31 61BE D032 ldvdpl movb *r2+,r0 ; get register data in r0 MSB 32 61C0 06C0 swpb r0 ; swap it over 33 61C2 06A0 bl @_vwtr ; write the register 33 61C4 789E 34 61C6 06C0 swpb r0 ; swap it back again 35 61C8 0580 inc r0 ; add 1 to register 36 61CA 0601 dec r1 ; finished? 37 61CC 16F8 jne ldvdpl ; repeat if not 38 ; set XMAX... 39 61CE D012 movb *r2,r0 ; get xmax 40 61D0 0880 sra r0,8 ; move to low byte 41 61D2 C800 mov r0,@xmax ; set xmax 41 61D4 A02C 42 61D6 05C7 inct r7 ; point to vdp r1 data 43 61D8 D817 movb *r7,@>83d4 ; write vdp r1 to >83d4 43 61DA 83D4 44 61DC D817 movb *r7,@VDPR1 ; save copy 44 61DE A06C 45 ; now clear the screen... 46 61E0 C060 mov @xmax,r1 ; calculate the character count 46 61E2 A02C 47 61E4 0200 li r0,24 ; according to the... 47 61E6 0018 48 61E8 3840 mpy r0,r1 ; ...text mode 49 61EA 04C0 clr r0 ; screen address 50 61EC 0201 li r1,>2000 ; space character 50 61EE 2000 51 61F0 06A0 bl @vsbwmi ; wipe screen 51 61F2 7880 52 61F4 04E0 clr @scrX ; zero x coordinate 52 61F6 A028 53 61F8 04E0 clr @scrY ; zero y coordinate 53 61FA A02A 54 61FC 0288 ci r8,1 ; was 32 column mode selected? 54 61FE 0001 55 6200 1613 jne gmodex ; if not, then exit 56 ; load colour table for pattern mode... 57 6202 0200 li r0,>380 ; color table 57 6204 0380 58 6206 0201 li r1,>f000 ; white on transparent 58 6208 F000 59 620A 0202 li r2,16 ; count 59 620C 0010 60 620E 06A0 bl @vsbwmi ; load colour table 60 6210 7880 61 ; initialise sprite attribute list... 62 6212 0200 li r0,>303 ; address of colour byte 62 6214 0303 63 6216 04C1 clr r1 ; transparent colour 64 6218 0202 li r2,32 ; 32 sprites 64 621A 0020 65 621C 06A0 dovdp2 bl @_vsbw0 ; write to sprite 65 621E 782C 66 6220 0220 ai r0,4 ; move to next sprite 66 6222 0004 67 6224 0602 dec r2 ; decrement count 68 6226 16FA jne dovdp2 ; repeat if not finished 69 6228 1017 gmodex jmp gexit 70 col40d ; register count and data 71 622A 0800 byte 8,>00,>f0,>00,>0e,>01,>06,>00,>f4 71 622C F000 71 622E 0E01 71 6230 0600 71 6232 F4 72 6233 28 byte 40 ; XMAX 73 col32d ; register count and data 74 6234 0800 byte 8,>00,>e0,>00,>0e,>01,>06,>02,>f4 74 6236 E000 74 6238 0E01 74 623A 0602 74 623C F4 75 623D 20 byte 32 ; XMAX 76 col80d ; register count and data 77 623E 0F04 byte 15,>04,>70,>03,>e8,>01,>06,>00,>f4,>88,>00,>00,>00,>94,>10,>00 77 6240 7003 77 6242 E801 77 6244 0600 77 6246 F488 77 6248 0000 77 624A 0094 77 624C 1000 78 624E 50 byte 80 ; XMAX 79 624F 0000 even 80 ;] 81 82 ;[ HCHAR ( y x ascii count -- ) 83 6250 06A0 _hchar bl @get4 ; get parameters from stack and calculate 83 6252 6592 84 ; screen address 85 6254 06A0 bl @_vsbwm ; write to screen 85 6256 7872 86 6258 0460 gexit b @retB0 86 625A 833A 87 ;] 88 89 ;[ VCHAR ( y x ascii count -- ) 90 625C 06A0 _vchar bl @get4 ; get parameters from stack and calculate 90 625E 6592 91 ; screen address 92 6260 0206 li r6,24 ; row count 92 6262 0018 93 6264 39A0 mpy @xmax,r6 ; max visible address+1 (in r7) 93 6266 A02C 94 6268 0607 dec r7 ; correct max visible (we count from 0) 95 626A C1A0 mov @xmax,r6 ; get xmax in a register 95 626C A02C 96 626E 06A0 vchar1 bl @_vsbw ; write a character 96 6270 781E 97 6272 A006 a r6,r0 ; move down one line 98 6274 81C0 c r0,r7 ; gone off end of screen? 99 6276 1201 jle vchar2 ; skip if not 100 6278 6007 s r7,r0 ; reduce address 101 627A 0602 vchar2 dec r2 ; decrement count 102 627C 16F8 jne vchar1 ; repeat if not finished 103 627E 10EC jmp gexit 104 ;] 105 106 ;[ GCHAR ( y x -- ascii ) 107 6280 06A0 _gchar bl @get2 ; get y & x from stack 107 6282 659A 108 6284 39A0 mpy @xmax,r6 ; compute y 108 6286 A02C 109 6288 A007 a r7,r0 ; compute screen address 110 628A 04C1 clr r1 ; use r1 for byte operations 111 628C 06A0 bl @_vsbr ; read byte from vdp 111 628E 77E4 112 6290 06C1 swpb r1 ; move byte to lsb 113 6292 0644 dect stack ; make space on stack 114 6294 C501 mov r1,*stack ; place on stack as 16 bit word 115 6296 10E0 jmp gexit 116 ;] 117 118 ;[ DCHAR ( address count ascii -- ) 119 ; Equivalent to CALL CHAR in BASIC. 120 ; Used to define a character. 121 ; Moves count words from address to ascii address in VDP memory 122 6298 06A0 _dchar bl @sget3 ; get 3 parameters 122 629A 658A 123 629C C249 mov r9,r9 ; if count=0 then... 124 629E 13DC jeq gexit ; ...just exit 125 62A0 C008 mov r8,r0 ; ascii 126 62A2 0A30 sla r0,3 ; multiply by 8 127 62A4 0220 ai r0,>800 ; add pattern table offset 127 62A6 0800 128 62A8 C04A mov r10,r1 ; source address 129 62AA C089 mov r9,r2 ; count 130 62AC 0A12 sla r2,1 ; convert from words to bytes 131 62AE 06A0 bl @_vmbw ; write to vdp 131 62B0 7846 132 62B2 10D2 jmp gexit 133 ;] 134 135 ;[ SPRITE ( sprite y x ascii color -- ) 136 ; sprite attribute list begins at 6*80h=300h 137 62B4 06A0 _sprit bl @sget5 ; get 5 parameters 137 62B6 6586 138 62B8 0A2A sla r10,2 ; multiply sprite by 4 (offset into SAL) 139 62BA 020B li r11,sal ; address of SAL in CPU ram 139 62BC A088 140 62BE 0200 li r0,>300 ; address of SAL in VDP ram 140 62C0 0300 141 62C2 A2CA a r10,r11 ; add offset to cpu addr according to 142 ; sprite number 143 62C4 C04B mov r11,r1 ; cpu source for vmbw 144 62C6 A00A a r10,r0 ; destination address for vmbw 145 62C8 06C6 swpb r6 ; rotate colour 146 62CA 06C7 swpb r7 ; rotate ascii 147 62CC 06C8 swpb r8 ; rotate x 148 62CE 06C9 swpb r9 ; rotate y 149 62D0 DEC9 movb r9,*r11+ ; move y to cpu buffer 150 62D2 DEC8 movb r8,*r11+ ; move x to cpu buffer 151 62D4 DEC7 movb r7,*r11+ ; move ascii to cpu buffer 152 62D6 DEC6 movb r6,*r11+ ; move colour to cpu buffer 153 62D8 0202 li r2,4 153 62DA 0004 154 62DC 06A0 bl @_vmbw 154 62DE 7846 155 62E0 0460 sprtx b @retB0 155 62E2 833A 156 ;] 157 158 ;[ MAGNIFY ( x -- ) 159 ; sets sprite magnification: 160 ; only the least significant bits are used: 161 ; bit 7: 1=magnified (0=not magnified) 162 ; bit 6: 1=double size (4 character) 163 ; Remember: TI number their bits backwards! Idiots! 164 62E4 C2B4 _magfy mov *stack+,r10 ; pop x 165 62E6 06CA swpb r10 ; get value in msb 166 62E8 024A andi r10,>0300 ; mask out any crap 166 62EA 0300 167 62EC 0200 li r0,>0001 ; vdp register number in lsb 167 62EE 0001 168 62F0 04C2 clr r2 ; prepare for byte operations 169 62F2 D0A0 movb @VDPR1,r2 ; get copy of VDP R1 169 62F4 A06C 170 62F6 0242 andi r2,>fc00 ; mask out magnification bits 170 62F8 FC00 171 62FA F282 socb r2,r10 ; OR in new magnification value 172 62FC D00A movb r10,r0 ; place in r0 msb 173 62FE D800 movb r0,@>83d4 ; place copy in 83d4 173 6300 83D4 174 6302 D800 movb r0,@VDPR1 ; reserve copy (VDP regs are read only) 174 6304 A06C 175 6306 06C0 swpb r0 ; rotate 176 6308 06A0 bl @_vwtr ; set the register 176 630A 789E 177 630C 10E9 jmp sprtx 178 ;] 179 180 ;[ SPRCOL ( sprite# colour -- ) 181 ; sets the colour of a sprite 182 630E C274 _spcol mov *stack+,r9 ; pop colour 183 6310 C2B4 mov *stack+,r10 ; pop sprite# 184 6312 0200 li r0,>300+3 ; SAL in vdp (offset to colour byte added) 184 6314 0303 185 6316 0208 li r8,SAL+3 ; SAL in CPU (offset to colour byte added) 185 6318 A08B 186 631A 0A2A sla r10,2 ; multiply sprite number by 4 187 631C A00A a r10,r0 ; point to correct address in vdp 188 631E A20A a r10,r8 ; point to correct address in CPU SAL 189 6320 06C9 swpb r9 ; rotate colour into MSB 190 6322 C049 mov r9,r1 ; into r1 for VSBW 191 6324 D609 movb r9,*r8 ; load into CPU SAL 192 6326 06A0 bl @_vsbw ; write colour byte into VDP 192 6328 781E 193 632A 10DA jmp sprtx 194 ;] 195 196 ;[ SPRLOC ( sprite y x -- ) 197 ; sets the location of a sprite 198 632C 06A0 _sploc bl @sget3 ; get 3 parameters from stack 198 632E 658A 199 6330 0200 li r0,>300 ; address of SAL in VDP 199 6332 0300 200 6334 0201 li r1,SAL ; address of SAL in CPU 200 6336 A088 201 6338 0A2A sla r10,2 ; get offset into tables 202 633A A00A a r10,r0 ; add to vdp addr 203 633C A04A a r10,r1 ; add to cpu addr 204 633E 06C8 swpb r8 ; rotate x 205 6340 06C9 swpb r9 ; rotate y 206 6342 DC49 movb r9,*r1+ ; write y to cpu SAL 207 6344 D448 movb r8,*r1 ; write x to cpu SAL 208 6346 0601 dec r1 ; point to beginning of entry in SAL 209 6348 0202 li r2,2 ; two bytes to write 209 634A 0002 210 634C 06A0 bl @_vmbw ; write to VDP 210 634E 7846 211 6350 10C7 jmp sprtx 212 ;] 213 214 ;[ SPRLOC? ( sprite -- y x ) 215 ; gets the location of a sprite 216 6352 C294 _spget mov *stack,r10 ; pop sprite# 217 6354 0200 li r0,sal ; address of SAL in CPU ram 217 6356 A088 218 6358 0A2A sla r10,2 ; get offset 219 635A A00A a r10,r0 ; point to correct address in SAL 220 635C 04C1 clr r1 ; prepare for byte operations 221 635E D070 movb *r0+,r1 ; get y and point to x 222 6360 06C1 swpb r1 ; move to lsb 223 6362 C501 mov r1,*stack ; place on stack 224 6364 0644 dect stack ; make new stack entry 225 6366 04C1 clr r1 226 6368 D050 movb *r0,r1 ; get x 227 636A 06C1 swpb r1 ; move to lsb 228 636C C501 mov r1,*stack ; place on stack 229 636E 10B8 jmp sprtx 230 ;] 231 232 ;[ SPRPAT ( sprite# ascii -- ) 233 ; sets the pattern of a sprite 234 6370 C274 _sppat mov *stack+,r9 ; pop ascii 235 6372 C2B4 mov *stack+,r10 ; pop sprite# 236 6374 0200 li r0,>300+2 ; address of SAL in vdp 236 6376 0302 237 6378 0202 li r2,SAL+2 ; address of SAL in cpu 237 637A A08A 238 637C 0A2A sla r10,2 ; calculate offset 239 637E A00A a r10,r0 ; offset into vdp 240 6380 A08A a r10,r2 ; offset into cpu 241 6382 06C9 swpb r9 ; rotate ascii into msb 242 6384 C049 mov r9,r1 ; for vsbw 243 6386 D489 movb r9,*r2 ; set in cpu ram 244 6388 06A0 bl @_vsbw ; set in vdp ram 244 638A 781E 245 638C 10A9 jmp sprtx 246 ;] 247 248 ;[ SPRVEC ( sprite y x -- ) 249 ; sets the Y and X movement offsets for sprite movement with SPRMOV 250 638E 06A0 _smlst bl @sget3 ; get 3 parameters 250 6390 658A 251 6392 0200 li r0,smlist ; address of sprite movement list 251 6394 A108 252 6396 0A1A sla r10,1 ; multiply sprite number by 2 253 6398 A00A a r10,r0 ; r0=address of appropriate entry in smlist 254 ; table. 255 639A 06C9 swpb r9 ; get y in MSB 256 639C 06C8 swpb r8 ; get x in MSB 257 639E DC09 movb r9,*r0+ ; load y into smlist 258 63A0 D408 movb r8,*r0 ; load x into smlist 259 63A2 109E jmp sprtx 260 ;] 261 262 ;[ SPRMOV ( start_sprite number_of_sprites -- ) 263 ; moves sprites according to the entries in SMLIST, starting from start_sprite 264 ; and continuing for number_of_sprites 265 ; 266 ; UPDATED MARCH 2012 SO THAT ONLY SPRITES WHO HAVE THEIR COORDINATES CHANGED 267 ; ARE ACTUALLY UPDATED IN VDP 268 63A4 C274 _spmov mov *stack+,r9 ; pop number of sprites 269 63A6 C2B4 mov *stack+,r10 ; pop start sprite 270 63A8 0749 abs r9 ; force positive & compare to zero. Nice. 271 63AA 139A jeq sprtx ; just exit if number of sprites=0 272 63AC C089 mov r9,r2 ; save no. of sprites to move in r2 273 63AE C2CA mov r10,r11 ; copy start sprite 274 63B0 C18A mov r10,r6 ; copy again 275 63B2 0A1A sla r10,1 ; adjust for start sprite smlist 276 63B4 022A ai r10,smlist ; point to correct entry in smlist 276 63B6 A108 277 63B8 0A2B sla r11,2 ; adjust destination for sal 278 63BA 022B ai r11,sal ; point to correct entry in the sal 278 63BC A088 279 63BE BEFA sprmv1 ab *r10+,*r11+ ; add y 280 63C0 BEFA ab *r10+,*r11+ ; add x 281 63C2 05CB inct r11 ; skip ascii code and colour in sal 282 63C4 0609 dec r9 ; decrement count 283 63C6 16FB jne sprmv1 ; repeat if not finished 284 63C8 0200 li r0,>300 ; vdp address of sal 284 63CA 0300 285 63CC 0A26 sla r6,2 ; calculate offset into sal 286 63CE A006 a r6,r0 ; calculate vdp sal address 287 63D0 0201 li r1,sal ; cpu address of sal 287 63D2 A088 288 63D4 A046 a r6,r1 ; calculate cpu source address of sal 289 63D6 0A22 sla r2,2 ; calculate number of bytes to write 290 63D8 06A0 bl @_vmbw ; copy cpu sal to vdp sal 290 63DA 7846 291 63DC 100B jmp gexit1 292 ;] 293 294 ;[ COLOR ( char_set foreground background -- ) 295 ; sets the color sets in 32 column mode 296 63DE 06A0 _color bl @sget3 ; get 3 parameters 296 63E0 658A 297 63E2 0200 li r0,>380 ; address of colour table 297 63E4 0380 298 63E6 A00A a r10,r0 ; point to correct colour set entry 299 63E8 0A49 sla r9,4 ; move foreground into ms nybble 300 63EA E209 soc r9,r8 ; OR foreground into background 301 63EC C048 mov r8,r1 ; move to r1 for vsbw 302 63EE 06C1 swpb r1 ; move to ms byte 303 63F0 06A0 bl @_vsbw0 ; write to vdp 303 63F2 782C 304 63F4 0460 gexit1 b @retB0 304 63F6 833A 305 ;] 306 307 ;[ SCREEN ( colour -- ) 308 ; sets the screen colour 309 63F8 C2B4 _scren mov *stack+,r10 ; pop colour 310 63FA 0200 li r0,>0700 ; vdp register number 310 63FC 0700 311 63FE 024A andi r10,>00ff ; mask out any crap 311 6400 00FF 312 6402 E00A soc r10,r0 ; or colour into register 313 6404 06A0 bl @_vwtr 313 6406 789E 314 6408 10F5 jmp gexit1 315 ;] 316 317 ;[ SCROLL ( direction -- ) 318 ; scrolls the screen, according to the coodinates in PANEL 319 ; 0=left 2=right 4=up 6=down 320 ; I'm not happy with these routines. I'm sure they could be shorter and faster 321 ; I'll have to revisit them later. 322 _scrol 323 640A C260 mov @panxy,r9 ; screen address to start 323 640C A032 324 640E C1A0 mov @panc,r6 ; column count 324 6410 A036 325 6412 C1E0 mov @panr,r7 ; row count 325 6414 A034 326 6416 0208 li r8,>2000 ; space character (used if no wrap around) 326 6418 2000 327 641A C2A0 mov @wrap,r10 ; get WRAP in a register 327 641C A030 328 641E C3E0 mov @xmax,r15 ; get xmax in a register 328 6420 A02C 329 6422 C820 mov @bank1_,@retbnk ; interrupts should return to bank 1 329 6424 606C 329 6426 A06E 330 ; check direction and call appropriate routine... 331 6428 0200 li r0,scrlut ; address of look up table 331 642A 6432 332 642C A034 a *stack+,r0 ; add and pop parameter to get address of 333 ; routine. 334 642E C010 mov *r0,r0 ; get the address in a register 335 6430 0450 b *r0 ; call the routine 336 6432 643A scrlut data _left,_right,_up,_down ; addresses of the routines to call 336 6434 6478 336 6436 64BE 336 6438 6512 337 338 ;[ ; left scroll... 339 _left ; read a line from screen into buffer... 340 643A C009 mov r9,r0 ; vdp address 341 643C C086 mov r6,r2 ; number of bytes to read 342 643E C060 mov @here,r1 ; cpu buffer 342 6440 A046 343 6442 06A0 bl @_vmbr2 ; read a line 343 6444 77FE 344 6446 C020 mov @here,r0 ; start of buffer 344 6448 A046 345 644A C040 mov r0,r1 ; one character to the right 346 644C 0581 inc r1 ; one character to the right 347 644E C28A mov r10,r10 ; check WRAP 348 6450 1602 jne _lwrap ; jump if true (wrap=on) 349 6452 D388 movb r8,r14 ; else load a space character for the 350 ; wrap-around. 351 6454 1001 jmp $+4 ; skip next instruction 352 6456 D390 _lwrap movb *r0,r14 ; save leftmost char for wrap around 353 6458 C086 mov r6,r2 ; x count 354 645A 0602 dec r2 ; point to end of line for wrap-around 355 645C DC31 _left1 movb *r1+,*r0+ ; copy character to the left 356 645E 0602 dec r2 ; reduce x count 357 6460 16FD jne _left1 ; loop if not finished 358 6462 D40E movb r14,*r0 ; copy saved character for wrap around 359 6464 C009 mov r9,r0 ; set screen address 360 6466 C060 mov @here,r1 ; source 360 6468 A046 361 646A C086 mov r6,r2 ; count 362 646C 06A0 bl @_vmbw2 ; write to screen 362 646E 784C 363 6470 0607 dec r7 ; finished? 364 6472 13C0 jeq gexit1 ; if so exit 365 6474 A24F a r15,r9 ; move down one line 366 6476 10E1 jmp _left ; repeat 367 ;] 368 369 ;[ ; right scroll... 370 _right ; read a line from screen into buffer... 371 6478 C009 mov r9,r0 ; vdp address 372 647A C086 mov r6,r2 ; number of bytes to read 373 647C C060 mov @here,r1 ; cpu buffer 373 647E A046 374 6480 06A0 bl @_vmbr2 ; read a line 374 6482 77FE 375 6484 C020 mov @here,r0 ; start of buffer 375 6486 A046 376 6488 A006 a r6,r0 ; end of buffer +1 377 648A 0600 dec r0 ; correct to point to end of buffer 378 648C C040 mov r0,r1 ; r1 will hold... 379 648E 0601 dec r1 ; ...end of buffer -1 380 6490 C28A mov r10,r10 ; check WRAP 381 6492 1602 jne _rwrap ; jump if true (wrap=on) 382 6494 D388 movb r8,r14 ; else load a space character for the 383 ; wrap-around 384 6496 1001 jmp $+4 ; skip next instruction 385 6498 D390 _rwrap movb *r0,r14 ; save leftmost char for wrap around 386 649A C086 mov r6,r2 ; x count 387 649C 0602 dec r2 ; point to end of line for wrap-around 388 649E D411 _right1 movb *r1,*r0 ; copy character to the left 389 64A0 0600 dec r0 ; decrement pointer 390 64A2 0601 dec r1 ; decrement pointer 391 64A4 0602 dec r2 ; reduce x count 392 64A6 16FB jne _right1 ; loop if not finished 393 64A8 D40E movb r14,*r0 ; copy saved character for wrap around 394 64AA C009 mov r9,r0 ; set screen address 395 64AC C060 mov @here,r1 ; source 395 64AE A046 396 64B0 C086 mov r6,r2 ; count 397 64B2 06A0 bl @_vmbw2 ; write to screen 397 64B4 784C 398 64B6 0607 dec r7 ; finished? 399 64B8 139D jeq gexit1 ; if so exit 400 64BA A24F a r15,r9 ; move down one line 401 64BC 10DD jmp _right ; repeat 402 ;] 403 404 ;[ ; up scroll... 405 64BE C28A _up mov r10,r10 ; check wrap 406 64C0 1306 jeq _up0 ; jump if no wrap 407 64C2 C009 mov r9,r0 ; top left address 408 64C4 C086 mov r6,r2 ; x count 409 64C6 0201 li r1,tib ; we'll use the terminal input buffer for storage 409 64C8 3420 410 64CA 06A0 bl @_vmbr2 ; read the liine 410 64CC 77FE 411 64CE C009 _up0 mov r9,r0 ; top left screen address to r0 412 64D0 A00F _up1 a r15,r0 ; move down one line 413 64D2 C060 mov @here,r1 ; buffer address 413 64D4 A046 414 64D6 C086 mov r6,r2 ; x count 415 64D8 06A0 bl @_vmbr2 ; read from screen 415 64DA 77FE 416 64DC 600F s r15,r0 ; move up a line 417 64DE C060 mov @here,r1 ; buffer address 417 64E0 A046 418 64E2 C086 mov r6,r2 ; number of bytes to write (x count) 419 64E4 06A0 bl @_vmbw2 ; write them 419 64E6 784C 420 64E8 0607 dec r7 ; decrement counter 421 64EA 1302 jeq _up2 ; exit if finished 422 64EC A00F a r15,r0 ; move down a line 423 64EE 10F0 jmp _up1 ; repeat 424 64F0 C28A _up2 mov r10,r10 ; check wrap 425 64F2 1306 jeq _up3 ; blank line if not required 426 64F4 0201 li r1,tib ; else get ready to write the buffered line 426 64F6 3420 427 64F8 C086 mov r6,r2 ; x count 428 64FA 06A0 bl @_vmbw2 ; write it 428 64FC 784C 429 64FE 1005 jmp _upout ; see ya 430 6500 0201 _up3 li r1,>2000 ; write a blank line 430 6502 2000 431 6504 C086 mov r6,r2 ; x count 432 6506 06A0 bl @_vsbwm2 ; write it 432 6508 7878 433 650A 04E0 _upout clr @tib ; clear tib 433 650C 3420 434 650E 0460 gexit2 b @retB0 434 6510 833A 435 ;] 436 437 ;[ ; down scroll... 438 6512 0607 _down dec r7 439 6514 C007 mov r7,r0 ; y length 440 6516 380F mpy r15,r0 ; convert to address (result in r1) 441 6518 A049 a r9,r1 ; add top of panel offset 442 651A C001 mov r1,r0 ; vdp address in r0 443 651C C28A mov r10,r10 ; check wrap 444 651E 1305 jeq _down0 ; skip if not required 445 6520 0201 li r1,tib ; we'll use the terminal input buffer for 445 6522 3420 446 ; storage 447 6524 C086 mov r6,r2 ; x count 448 6526 06A0 bl @_vmbr2 ; read the line 448 6528 77FE 449 652A 600F _down0 s r15,r0 ; move up a line 450 652C C060 mov @here,r1 ; buffer address 450 652E A046 451 6530 C086 mov r6,r2 ; x count 452 6532 06A0 bl @_vmbr2 ; read a line 452 6534 77FE 453 6536 A00F a r15,r0 ; move down a line 454 6538 C060 mov @here,r1 ; buffer address 454 653A A046 455 653C C086 mov r6,r2 ; x count 456 653E 06A0 bl @_vmbw2 ; write it 456 6540 784C 457 6542 0607 dec r7 ; decrement line count 458 6544 1302 jeq _down1 ; jump if finished 459 6546 600F s r15,r0 ; otherwise move up a line 460 6548 10F0 jmp _down0 ; and repeat 461 654A 600F _down1 s r15,r0 ; up a line 462 654C C28A mov r10,r10 ; check wrap 463 654E 1306 jeq _down2 ; blank line if not required 464 6550 0201 li r1,tib ; source 464 6552 3420 465 6554 C086 mov r6,r2 ; x count 466 6556 06A0 bl @_vmbw2 ; write saved line 466 6558 784C 467 655A 1005 jmp _dnout ; see ya 468 655C 0201 _down2 li r1,>2000 ; write a blank line 468 655E 2000 469 6560 C086 mov r6,r2 ; x count 470 6562 06A0 bl @_vsbwm2 ; write it 470 6564 7878 471 6566 04E0 _dnout clr @tib ; clear tib 471 6568 3420 472 656A 10D1 jmp gexit2 473 ;] 474 ;] 475 476 ;[ PANEL ( x y xl yl -- ) 477 ; defines a screen panel to be used by SCROLL 478 _panel 479 656C 06A0 bl @sget4 ; get 4 parameters off stack 479 656E 6588 480 6570 C009 mov r9,r0 ; move y 481 6572 3820 mpy @xmax,r0 ; multiply y by line length 481 6574 A02C 482 6576 A04A a r10,r1 ; add x 483 6578 C801 mov r1,@panxy ; save it 483 657A A032 484 657C C807 mov r7,@panr ; save yl 484 657E A034 485 6580 C808 mov r8,@panc ; save xl 485 6582 A036 486 6584 10C4 jmp gexit2 487 ;] 488 489 ;[ 490 ; subroutine to get parameters off the stack 491 6586 C1B4 sget5 mov *stack+,r6 492 6588 C1F4 sget4 mov *stack+,r7 493 658A C234 sget3 mov *stack+,r8 494 658C C274 mov *stack+,r9 495 658E C2B4 mov *stack+,r10 496 6590 045B rt 497 ;] 498 499 ;[ 500 ; subroutine to get parameters off the stack for HCHAR VCHAR and GCHAR 501 ; Has two entry points: 502 ; get4: gets four parameters (HCHAR & VHCAR) 503 ; get2: gets two parameters (GCHAR) 504 6592 C0B4 get4 mov *stack+,r2 ; pop count 505 6594 1308 jeq gabort ; if count=0 then cancel the instruction 506 6596 C074 mov *stack+,r1 ; pop ascii 507 6598 06C1 swpb r1 ; move to high byte 508 659A C034 get2 mov *stack+,r0 ; pop x 509 659C C1B4 mov *stack+,r6 ; pop y 510 659E 39A0 mpy @xmax,r6 ; multiply by screen size 510 65A0 A02C 511 65A2 A007 a r7,r0 ; calculate screen start address 512 65A4 045B rt 513 65A6 0224 gabort ai stack,6 ; pop remaining parameters off the stack 513 65A8 0006 514 65AA 0460 b @retB0 ; and just exit 514 65AC 833A 515 ;] * * COPY 'C:\TI\Source\TurboForth\Bank1\1-04-Memory.a99' * 1 ; __ __ 2 ; | \/ | /\ 3 ; | \ / | ___ _ __ ___ ___ _ __ _ _ / \ ___ ___ ___ ___ ___ 4 ; | |\/| |/ _ \ '_ ` _ \ / _ \| '__| | | | / /\ \ / __|/ __|/ _ | __/ __| 5 ; | | | | __/ | | | | | (_) | | | |_| | / ____ \ (__| (__| __|__ \__ \ 6 ; |_| |_|\___|_| |_| |_|\___/|_| \__, | /_/ \_\___|\___|\___|___/___/ 7 ; Memory access words __/ | 8 ; |___/ 9 ;[ FILL ( addr count value -- ) 10 65AE 06A0 _fill bl @sget3 ; get 3 parameters 10 65B0 658A 11 65B2 C249 mov r9,r9 ; if value=0 then... 12 65B4 131A jeq cmvext ; ...just exit 13 65B6 06C8 swpb r8 ; get byte value in msb 14 65B8 DE88 filllp movb r8,*r10+ ; move to addr and increment addr 15 65BA 0609 dec r9 ; finished? 16 65BC 16FD jne filllp ; repeat if not 17 65BE 1015 jmp cmvext ; clean up and exit 18 ;] 19 20 ;[ CMOVE ( addr1 addr2 count -- ) 21 ; Move count bytes beginning at address addr1 to addr2. The byte at addr1 is 22 ; moved first, proceeding toward high memory. If count is zero nothing is moved 23 65C0 06A0 _cmove bl @sget3 ; get 3 parameters 23 65C2 658A 24 65C4 C208 mov r8,r8 ; if count=0 then... 25 65C6 1311 jeq cmvext ; ...just exit 26 65C8 DE7A cmovlp movb *r10+,*r9+ ; move a byte 27 65CA 0608 dec r8 ; finished? 28 65CC 16FD jne cmovlp ; repeat if not 29 65CE 100D jmp cmvext ; clean up and exit 30 ;] 31 32 ;[ CMOVE> ( addr1 addr2 count -- ) 33 ; Move the count bytes at address addr1 to addr2. The move begins by moving the 34 ; byte at addr1 plus count minus 1 to addr2 plus count minus 1 and proceeds to 35 ; successively lower addresses for count bytes. 36 ; If count is zero nothing is moved. 37 ; (Useful for sliding a string towards higher addresses) 38 65D0 06A0 _cmovf bl @sget3 ; get 3 parameters 38 65D2 658A 39 65D4 C208 mov r8,r8 ; if count=0 then... 40 65D6 1309 jeq cmvext ; ...just exit 41 65D8 0608 dec r8 ; count-1 42 65DA A248 a r8,r9 ; addr2=addr2+count-1 43 65DC A288 a r8,r10 ; addr1=addr1+count-1 44 65DE 0588 inc r8 ; restore count 45 65E0 D65A cmvflp movb *r10,*r9 ; move a byte 46 65E2 060A dec r10 ; decrement addr 1 47 65E4 0609 dec r9 ; decrement addr 2 48 65E6 0608 dec r8 ; decrement count 49 65E8 16FB jne cmvflp ; loop if not finished 50 65EA 0460 cmvext b @retB0 50 65EC 833A 51 ;] 52 53 ;[ COPYW (source destination count -- ) 54 ; copy WORDS from source to destination for 'count' words 55 ; no action taken if count=0 56 65EE 06A0 _copyw bl @sget3 56 65F0 658A 57 65F2 C208 mov r8,r8 ; if count=0 then... 58 65F4 13FA jeq cmvext ; ...just exit 59 65F6 CE7A copywl mov *r10+,*r9+ ; copy a word 60 65F8 0608 dec r8 ; decrement counter 61 65FA 16FD jne copywl ; loop if counter not zero 62 65FC 10F6 jmp cmvext ; clean up and exit 63 ;] 64 65 ;[ ; >MAP ( bank address -- ) 66 ; If a SAMS card is present, maps memory bank "bank" to address "address" 67 65FE C2CC _sams mov r12,r11 ; save address of NEXT 68 6600 C074 mov *stack+,r1 ; get address 69 6602 0241 andi r1,>f000 ; set to 4k boundary 69 6604 F000 70 6606 09B1 srl r1,11 ; divide by 2048 71 6608 0221 ai r1,>4000 ; convert to SAMS register address 71 660A 4000 72 660C C0B4 mov *stack+,r2 ; get bank 73 660E 0242 andi r2,>ff ; mask off any crap 73 6610 00FF 74 6612 C002 mov r2,r0 ; keep a copy 75 6614 0A82 sla r2,8 ; move to high byte 76 6616 2880 xor r0,r2 ; combine r0 & r2. Hi & lo bytes are now identical 77 6618 020C li r12,>1e00 ; cru address of SAMS 77 661A 1E00 78 661C 1D00 sbo 0 ; enable SAMS registers 79 661E C442 mov r2,*r1 ; poke sams register 80 6620 1E00 sbz 0 ; disable sams registers 81 6622 C30B mov r11,r12 ; restore address of NEXT 82 6624 0460 b @retB0 ; return to caller 82 6626 833A 83 84 ;] * * COPY 'C:\TI\Source\TurboForth\Bank1\1-05-Speech.a99' * 1 ; _____ _ __ __ _ 2 ; / ____| | | \ \ / / | | 3 ; | (___ _ __ ___ ___ ___| |__ \ \ /\ / /___ _ __ __| |___ 4 ; \___ \| '_ \ / _ \/ _ \/ __| '_ \ \ \/ \/ // _ \| '__/ _` / __| 5 ; ____) | |_) | __/ __/ (__| | | | \ /\ /| (_) | | | (_| \__ \ 6 ; |_____/| .__/ \___|\___|\___|_| |_| \/ \/ \___/|_| \__,_|___/ 7 ; | | 8 ; |_| 9 10 0000 9000 spchrd equ >9000 ; speech read register 11 0000 9400 spchwt equ >9400 ; speech write register 12 13 6628 10 spread byte 16 ; 'read data' command code 14 6629 AA ssflag byte >aa ; 'speech synth present' check code 15 662A 50 spkROM byte >50 ; 'speak from ROM' command code 16 662B 0000 even 17 18 ;[ TALKING? ( -- flag ) 19 ; returns 0 if speech synth is idle, else returns 1 20 ; Upon testing, it appears that the synth reports idle *just before* it really 21 ; is finished. 22 ; This causes a problem, as TurboForth is fast enough to start feeding new data 23 ; immediately when it detects the synth as idle, thus chopping off the end of 24 ; streamed speech. 25 ; To protect against this, it uses the hardware busy signal from the synth, 26 ; *and* the number of bytes/words currently outstanding in any data that is 27 ; currently being fed to the synth. If either>0 then a busy is returned. 28 662C 0644 _spkng dect stack ; make space on data stack 29 662E C020 mov @synyes,r0 ; synth fitted? 29 6630 A040 30 6632 130B jeq nspk ; if not then just return 'not speaking' 31 6634 06A0 bl @spstat ; else get status from speech synth 31 6636 8340 32 6638 C020 mov @spdata,r0 ; get the data from speech synth 32 663A 834A 33 663C 0240 andi r0,>8000 ; isolate busy bit 33 663E 8000 34 6640 A020 a @spcnt,r0 ; add words/bytes remaining in speech buffer 34 6642 A03A 35 6644 1302 jeq nspk ; not speaking 36 6646 0714 seto *stack ; speaking 37 6648 100D jmp sayxit ; return via r15 38 664A 04D4 nspk clr *stack ; not speaking 39 664C 100B jmp sayxit 40 ;] 41 42 ;[ SAY ( addr count -- ) 43 ; feeds count words to the speech synth, starting at addr. Used to speak words 44 ; from the built in speech rom. The data fed to the synth should be the entry 45 ; addresses of speech rom words, as found in the editor assembler manual. 46 664E C834 _say mov *stack+,@spcnt ; pop speech buffer count 46 6650 A03A 47 6652 C834 mov *stack+,@spadr ; pop speech buffer address 47 6654 A03C 48 6656 C020 mov @synyes,r0 ; check if speech synth is fitted 48 6658 A040 49 665A 1304 jeq sayxit ; if not, just exit immediately 50 665C 0200 li r0,romspk ; else get address of rom-speak routine 50 665E 60FA 51 6660 C800 mov r0,@spcsvc ; load into speech service routine pointer 51 6662 A03E 52 6664 0460 sayxit b @retB0 52 6666 833A 53 ;] 54 55 ;[ STREAM ( addr count -- ) 56 ; feeds addr bytes to the speech synth, starting at addr. Used to stream raw 57 ; speech data to the speech synth. 58 6668 C034 _strem mov *stack+,r0 ; pop speech buffer count 59 666A 0A10 sla r0,1 ; convert to byte count 60 666C C800 mov r0,@spcnt ; store it 60 666E A03A 61 6670 C834 mov *stack+,@spadr ; pop speech buffer address 61 6672 A03C 62 6674 C020 mov @synyes,r0 ; check if speech synth is fitted 62 6676 A040 63 6678 13F5 jeq sayxit ; just exit if not 64 667A 0200 li r0,strspk ; else get address of stream-speak routine 64 667C 6090 65 ; (defined in 1-01-ISR.a99) 66 667E C800 mov r0,@spcsvc ; load into speech service routine pointer 66 6680 A03E 67 6682 10F0 jmp sayxit 68 ;] 69 70 ;[ speech support routines 71 ; routine to see if speech synth is fitted 72 ; on exit sets r0: 0=not detected >ffff=detected 73 6684 04E0 isspch clr @synyes ; assume no speech synth detected 73 6686 A040 74 6688 04C0 clr r0 ; check address 0 in speech synth 75 668A 06A0 bl @readsp ; read byte from the speech synth in r0 msb 75 668C 669C 76 668E 9800 cb r0,@ssflag ; is the speech synth here? 76 6690 6629 77 6692 1301 jeq spyes ; speech synth is detected 78 6694 10E7 jmp sayxit ; see ya 79 6696 0720 spyes seto @synyes ; found speech synth 79 6698 A040 80 669A 10E4 spchx jmp sayxit ; gtf outta here 81 82 83 ; routine to read a byte from the speech synth 84 ; Inputs: R0=address in speech synth to read 85 ; Outputs R0=byte read from speech synth in MSB 86 669C C20B readsp mov r11,r8 ; save return address 87 669E 06A0 bl @spaddr ; load address into speech synth (in r0) 87 66A0 66B2 88 66A2 D820 movb @spread,@spchwt ; send read data command 88 66A4 6628 88 66A6 9400 89 66A8 0BC0 src r0,12 ; 12uS delay 90 66AA 04C0 clr r0 ; prepare for byte operations 91 66AC D020 movb @spchrd,r0 ; read the byte from the speech synth 91 66AE 9000 92 66B0 0458 b *r8 ; return to caller 93 94 95 ; routine to load an address into the speech synth's address register 96 ; the address to load is passed in r0 97 66B2 0202 spaddr li r2,4 ; 4 nybbles to load 97 66B4 0004 98 66B6 0B40 loadlp src r0,4 ; start with least significant nybble 99 66B8 C040 mov r0,r1 ; copy it 100 66BA 0B41 src r1,4 ; get target nybble into correct position 101 66BC 0241 andi r1,>0f00 ; mask out the nybble of interest 101 66BE 0F00 102 66C0 0261 ori r1,>4000 ; put in 4x00 format for speech synth 102 66C2 4000 103 66C4 D801 movb r1,@spchwt ; send it to the speech synth 103 66C6 9400 104 66C8 0602 dec r2 ; finished? 105 66CA 16F5 jne loadlp ; do next nybble repeat if not 106 66CC 0201 li r1,>4000 ; signal to speech synth that we finished... 106 66CE 4000 107 66D0 D801 movb r1,@spchwt ; ...sending the address. 107 66D2 9400 108 66D4 045B rt ; return to caller 109 ;] 110 111 ;[ (DATA) - runtime code for DATA 112 66D6 0644 _data dect stack ; make stack entry 113 66D8 C503 mov pc,*stack ; current address to stack 114 66DA 05D4 inct *stack ; plus 2 115 66DC 0644 dect stack ; stack entry 116 66DE C073 mov *pc+,r1 ; number of data items... 117 66E0 C501 mov r1,*stack ; ...to stack 118 66E2 0A11 sla r1,1 ; compute byte offset past data 119 66E4 A0C1 a r1,pc ; adjust program counter 120 66E6 0460 b @retB0 120 66E8 833A 121 ;] * * COPY 'C:\TI\Source\TurboForth\Bank1\1-06-Blocks.a99' * 1 ; ____ _ _ _____ ______ __ __ _ 2 ; | _ \| | | | |_ _| / / __ \ \ \ / / | | 3 ; | |_) | | ___ ___| | __ | | / / | | | \ \ /\ / /___ _ __ __| |___ 4 ; | _ <| |/ _ \ / __| |/ / | | / /| | | | \ \/ \/ // _ \| '__/ _` / __| 5 ; | |_) | | (_) | (__| < _| |_ / / | |__| | \ /\ /| (_) | | | (_| \__ \ 6 ; |____/|_|\___/ \___|_|\_\ |_____/_/ \____/ \/ \/ \___/|_| \__,_|___/ 7 ; block file system words & subroutines 8 ; Some heavy stuff in here. In here be demons. 9 ; Turn back all ye faint of heart... 10 11 ;[ pab opcodes 12 0000 0000 open equ 0 ; open opcode 13 0000 0001 close equ >1 ; close opcode 14 0000 0002 read equ >2 ; read opcode 15 0000 0003 write equ >3 ; write opcode 16 0000 0004 fwdrew equ >4 ; restore/rewind opcode (fwd/rew) 17 0000 0009 status equ >9 ; status op-code 18 ;] 19 20 ;[ USE ( addr len -- ) 21 ; Tells the system which block file to use for block IO 22 ; e.g. USE DSK1.BLOCKS 23 ; Simply sets the filename and length in the blockIO PAB 24 ; Syntax: S" DSKn.FILENAME" USE 25 66EA C0B4 _use mov *stack+,r2 ; length of filename 26 66EC 06C2 swpb r2 ; move to MSB 27 66EE C034 mov *stack+,r0 ; address of file name 28 66F0 0209 li r9,pabnln ; address of filename length in blockIO PAB 28 66F2 A189 29 66F4 DE42 movb r2,*r9+ ; write length to PAB length byte, now 30 ; pointing at filename 31 66F6 06C2 swpb r2 ; move to LSB 32 66F8 DE70 _use3 movb *r0+,*r9+ ; copy byte of filename to pab 33 66FA 0602 dec r2 ; finished copying? 34 66FC 16FD jne _use3 ; repeat if not 35 ; clear all blk pointers... 36 66FE 04E0 clr @lstblk 36 6700 A1B4 37 6702 04E0 clr @blk0 37 6704 A1B6 38 6706 04E0 clr @blk1 38 6708 A1BA 39 670A 04E0 clr @blk2 39 670C A1BE 40 670E 04E0 clr @blk3 40 6710 A1C2 41 6712 04E0 clr @blk4 41 6714 A1C6 42 6716 04E0 clr @blk5 42 6718 A1CA 43 671A 0460 usexit b @retB0 43 671C 833A 44 ;] 45 46 ;[ BLOCK ( block# -- addr ) 47 ; Brings a block into a buffer, if not already in memory 48 ; 1) If already in memory, the block is not re-loaded from device 49 ; 2) If not in memory: 50 ; 3) Scans for a free buffer 51 ; 4) If no free buffer: 52 ; 5) flush all buffers back to device 53 ; 6) Repeat from 3 54 ; 7) If free buffer: 55 ; 9) Load block from device into free buffer 56 ; 10) Return address of buffer 57 ; 11) If disk error, or block not found etc, return 0 58 ; Note: If a block number of 0 is given 0 is returned 59 671E 04E0 _block clr @errnum ; clear last disk io error 59 6720 A038 60 6722 C014 mov *stack,r0 ; block number in r0 for scnblk 61 6724 13FA jeq usexit ; if zero then just exit 62 6726 C800 mov r0,@lstblk ; update last block accessed (for UPDATE) 62 6728 A1B4 63 672A 06A0 bl @scnblk ; see if the block is already in memory 63 672C 69A0 64 672E C041 mov r1,r1 ; check returned result 65 6730 1303 jeq blknim ; block is not in memory 66 6732 05C1 inct r1 ; block is in memory. point to vdp address 67 ; pointer 68 6734 C511 mov *r1,*stack ; place vdp address on stack 69 6736 10F1 jmp usexit ; exit 70 ; look for a free buffer 71 6738 06A0 blknim bl @frebuf ; block is not in memory, scan for a buffer 71 673A 6988 72 673C C000 mov r0,r0 ; check returned result 73 673E 1328 jeq bnfb ; jump if no free buffers 74 ; we have a free buffer, it's blk address is in r0... 75 6740 C414 blkfb mov *stack,*r0 ; update block indicator in block buffer 76 6742 C200 mov r0,r8 ; copy blk address 77 6744 C090 mov *r0,r2 ; copy block number 78 6746 0602 dec r2 ; reduce by one (so we can use block 0) 79 6748 0A32 sla r2,3 ; calculate record number (block no. x 8) 80 674A 05C0 inct r0 ; point to vdp address 81 674C C250 mov *r0,r9 ; save vdp address 82 674E C509 mov r9,*stack ; place vdp address on stack 83 ; put the pab into vdp ram, with an open opcode and open the file... 84 6750 0201 li r1,>8000 ; logical record length: 128 bytes (in msb) 84 6752 8000 85 6754 D801 movb r1,@pablrl ; set logical record length in pab 85 6756 A184 86 6758 C802 mov r2,@pabrec ; set record number in PAB 86 675A A186 87 675C C809 mov r9,@pabbuf ; address to load data into in VDP 87 675E A182 88 6760 06A0 bl @diskio ; witchcraft 88 6762 69B8 89 6764 0005 byte open,5 ; dis/fix input 90 6766 1319 jeq blkerr ; jump if an an error occurred 91 ; read 8 128 byte records (1K)... 92 6768 0207 li r7,8 ; 8 records to read 92 676A 0008 93 676C 06A0 blknxt bl @diskio ; call disk system 93 676E 69B8 94 6770 0205 byte read,5 ; dis/fix input 95 6772 1313 jeq blkerr ; jump if an an error occurred 96 6774 0229 ai r9,128 ; increment vdp address 96 6776 0080 97 6778 C809 mov r9,@pabbuf ; address to load data into in VDP 97 677A A182 98 677C 05A0 inc @pabrec ; set next record in PAB 98 677E A186 99 6780 0607 dec r7 ; finished reading all the records? 100 6782 16F4 jne blknxt ; repeat if not 101 6784 06A0 bl @diskio ; more alchemy 101 6786 69B8 102 6788 0105 byte close,5 ; dis/fix input 103 678A 06A0 bl @rstsp ; restore code in scratchpad 103 678C 6AEE 104 ; (destroyed by DSR access) 105 678E 10C5 jmp usexit ; exit 106 ; no free buffers :-( we need to do a flush... 107 6790 06A0 bnfb bl @flush1 ; flush all our buffers to device 107 6792 67B4 108 6794 0200 li r0,blk0 ; point to first (which is now free) block 108 6796 A1B6 109 6798 10D3 jmp blkfb ; repeat 110 ; an error occurred, return 0 on the stack 111 679A 04D4 blkerr clr *stack ; zero the TOS 112 679C 06C0 swpb r0 113 679E C800 mov r0,@errnum ; set disk io error number 113 67A0 A038 114 67A2 06A0 bl @diskio ; close the file 114 67A4 69B8 115 67A6 0105 byte close,5 116 67A8 06A0 bl @rstsp ; restore code in scratchpad 116 67AA 6AEE 117 ; (destroyed by DSR access) 118 67AC 10B6 jmp usexit ; exit 119 ;] 120 121 ;[ FLUSH ( -- ) 122 ; Flushes all dirty blocks back to disk 123 ; If a blocks' DIRTY flag is set, the block is physically written back to disk. 124 ; If the block is NOT dirty, it's (BLK) status is simply set to un-used. 125 ; Sets DSKERR to reflect disk DSR error status (0=no error) 126 67AE 06A0 _flush bl @flush1 126 67B0 67B4 127 67B2 10B3 flushx jmp usexit 128 67B4 04E0 flush1 clr @errnum ; reset last disk io error 128 67B6 A038 129 67B8 C38B mov r11,r14 ; save return address of caller 130 67BA 0206 li r6,6 ; 6 buffers to check 130 67BC 0006 131 67BE 0207 li r7,blk0+2 ; start with the first vdp address pointer 131 67C0 A1B8 132 67C2 C217 flnext mov *r7,r8 ; get address 133 67C4 0248 andi r8,>8000 ; check dirty flag 133 67C6 8000 134 67C8 1325 jeq flush2 ; if 0, not dirty, just reset pointers 135 ; else flush to disk... 136 67CA 0201 li r1,>8000 ; logical record length: 128 bytes (in msb) 136 67CC 8000 137 67CE D801 movb r1,@pablrl ; set logical record length 137 67D0 A184 138 67D2 04E0 clr @pabrec ; set record number to 0 138 67D4 A186 139 67D6 06A0 bl @diskio 139 67D8 69B8 140 67DA 0001 byte open,1 ; dis/fixed update 141 67DC 132A jeq flerr ; jump if error 142 67DE 020C li r12,8 ; 8 128 byte records (1024 bytes) 142 67E0 0008 143 67E2 C217 mov *r7,r8 ; vdp address 144 67E4 0248 andi r8,>7fff ; remove dirty bit 144 67E6 7FFF 145 67E8 C067 mov @-2(r7),r1 ; get block number 145 67EA FFFE 146 67EC 0601 dec r1 147 67EE 0A31 sla r1,3 ; convert to record count 148 67F0 C801 mov r1,@pabrec ; set record number 148 67F2 A186 149 67F4 C808 flnrec mov r8,@pabbuf ; set source vdp address 149 67F6 A182 150 67F8 06A0 bl @diskio ; write the record to disk 150 67FA 69B8 151 67FC 0301 byte write,1 ; dis/fix update 152 67FE 1319 jeq flerr ; jump if error 153 6800 0228 ai r8,128 ; next 128 bytes of vdp 153 6802 0080 154 6804 05A0 inc @pabrec ; next record on disk 154 6806 A186 155 6808 060C dec r12 ; decrement counter 156 680A 16F4 jne flnrec ; loop if not finished 157 680C 06A0 bl @diskio ; close the file 157 680E 69B8 158 6810 0101 byte close,1 ; dis/fix update 159 6812 130F jeq flerr ; jump if error 160 ; reset blk & dirty flag... 161 6814 04E7 flush2 clr @-2(r7) ; clear blk indicator 161 6816 FFFE 162 6818 C057 mov *r7,r1 ; get vdp address from pointer 163 681A 0241 andi r1,>7fff ; reset dirty bit 163 681C 7FFF 164 681E C5C1 mov r1,*r7 ; write it back 165 ; loop back for remaining blks... 166 6820 0227 ai r7,4 ; point to next vdp address 166 6822 0004 167 6824 0606 dec r6 ; finished? 168 6826 16CD jne flnext ; repeat if not 169 6828 020C flexit li r12,_next ; restore pointer to NEXT 169 682A 8326 170 682C 06A0 bl @rstsp ; restore code in scratchpad (destroyed by 170 682E 6AEE 171 ; DSR access) 172 6830 045E b *r14 ; return to caller 173 ; an error occurred... exit... 174 6832 06C0 flerr swpb r0 ; move error into low byte 175 6834 C800 mov r0,@errnum ; set DSKERR with error code 175 6836 A038 176 6838 06A0 bl @diskio ; set the file to closed 176 683A 69B8 177 683C 0101 byte close,1 178 683E 10F4 jmp flexit 179 ;] 180 181 ;[ UPDATE ( -- ) 182 ; marks the last accessed block as dirty so that it will subsequently be flushed 183 ; to disk. 184 6840 C020 _updat mov @lstblk,r0 ; get current block 184 6842 A1B4 185 6844 06A0 bl @scnblk ; locate it (blk address in r1) 185 6846 69A0 186 6848 05C1 inct r1 ; point to VDP address pointer 187 684A C011 mov *r1,r0 ; get the VDP address 188 684C 0260 ori r0,>8000 ; set dirty bit 188 684E 8000 189 6850 C440 mov r0,*r1 ; write it back 190 6852 10AF jmp flushx 191 ;] 192 193 ;[ EMPTY-BUFFERS ( -- ) 194 ; marks all buffers as unused. 195 6854 0202 _mtbuf li r2,6 ; counter 195 6856 0006 196 6858 0200 li r0,blk0 ; address of first blk 196 685A A1B6 197 685C 04F0 mtbufl clr *r0+ ; zero block number then point to vdp 198 ; address 199 685E C050 mov *r0,r1 ; get vdp address 200 6860 0241 andi r1,>7fff ; set dirty to zero 200 6862 7FFF 201 6864 CC01 mov r1,*r0+ ; write it back, point to next blk 202 6866 0602 dec r2 ; decrement counter 203 6868 16F9 jne mtbufl ; repeat if not finished 204 686A 04E0 clr @lstblk ; no blocks in memory 204 686C A1B4 205 686E 10A1 jmp flushx 206 ;] 207 208 ;[ CLEAN ( buffer -- ) 209 ; forces a buffers' status to clean 210 6870 06A0 _clean bl @cba ; compute blk address 210 6872 6978 211 6874 0241 andi r1,>7fff ; reset dirty bit 211 6876 7FFF 212 6878 C401 mov r1,*r0 ; write it back 213 687A 109B jmp flushx 214 215 ;] 216 217 ;[ DIRTY ( buffer -- ) 218 ; forces a buffers' status to dirty 219 687C 06A0 _dirty bl @cba ; compute blk address 219 687E 6978 220 6880 0261 ori r1,>8000 ; set dirty bit 220 6882 8000 221 6884 C401 mov r1,*r0 ; write it back 222 6886 1095 jmp flushx 223 ;] 224 225 ;[ DIRTY? ( buffer -- flag ) 226 ; interrogates a buffers' status, returning true if the buffer is dirty, else 227 ; returning false 228 6888 06A0 _qdirt bl @cba ; compute blk address 228 688A 6978 229 688C 0644 dect stack ; make space on stack (cba reduces stack 230 ; pointer) 231 688E 0241 andi r1,>8000 ; mask out everything except dirty bit 231 6890 8000 232 6892 1303 jeq ndirt ; if 0 then it's not dirty 233 6894 0714 seto *stack ; it's dirty 234 6896 0460 b @retB0 234 6898 833A 235 689A 04D4 ndirt clr *stack ; it's clean 236 689C 108A jmp flushx 237 ;] 238 239 ;[ BLK? ( buffer -- block vdp_address ) 240 ; For a given buffer, returns the actual block stored in that buffer 241 ; and the vdp address of that buffer 242 689E 06A0 _blkq bl @cba ; compute blk address 242 68A0 6978 243 68A2 0644 dect stack ; make space on stack 244 68A4 0640 dect r0 ; point to blk 245 68A6 C510 mov *r0,*stack ; place on stack 246 68A8 0241 andi r1,>7fff ; mask out dirty bit 246 68AA 7FFF 247 68AC 0644 dect stack 248 68AE C501 mov r1,*stack ; place vdp address of buffer on stack 249 68B0 1080 jmp flushx 250 ;] 251 252 ;[ BUF? ( block -- buffer vdp_address ) 253 ; For a given block, return the buffer number, and the vdp address of the buffer 254 ; returns 0 0 if the block is not in memory 255 68B2 C054 _buf mov *stack,r1 ; get block 256 68B4 0202 li r2,0 ; six buffers to check 256 68B6 0000 257 68B8 0200 li r0,blk0 ; point to top of buffer descriptor table 257 68BA A1B6 258 68BC 8050 bufrpt c *r0,r1 ; compare block to block being sought 259 68BE 130A jeq fndbuf ; jump if we found it 260 68C0 0220 ai r0,4 ; else point to next buffer in the table 260 68C2 0004 261 68C4 0582 inc r2 ; increment counter 262 68C6 0282 ci r2,6 ; finished? 262 68C8 0006 263 68CA 16F8 jne bufrpt 264 68CC 04D4 clr *stack ; the block was not found - return 0 0 265 68CE 0644 dect stack ; new stack entry 266 68D0 04D4 clr *stack 267 68D2 1004 jmp bufxit 268 68D4 C502 fndbuf mov r2,*stack ; push buffer number 269 68D6 0644 dect stack ; new stack entry 270 68D8 05C0 inct r0 ; point to vdp address 271 68DA C510 mov *r0,*stack ; push it to stack 272 68DC 0460 bufxit b @retB0 272 68DE 833A 273 ;] 274 275 ;[ SETBLK ( buffer block -- ) 276 ; For a given buffer, changes the block that it is associated with. 277 ; Allows blocks to copied to other blocks, using FLUSH. 278 68E0 C074 _setbk mov *stack+,r1 ; pop the block 279 68E2 C0B4 mov *stack+,r2 ; pop the buffer 280 68E4 0A22 sla r2,2 ; multiply buffer by 4 to act as offset into 281 ; buffer descriptor table 282 68E6 0200 li r0,blk0 ; point to top of buffer descriptor table 282 68E8 A1B6 283 68EA A002 a r2,r0 ; point to correct entry in buffer 284 ; descriptor table 285 68EC C401 mov r1,*r0 ; change block entry 286 68EE 10F6 jmp bufxit 287 ;] 288 289 ;[ MKBLK ( filename size_in_kilobytes -- ) 290 ; makes a block file on disk. Sets DSKERR with result code. >0=some error 291 68F0 04E0 _mkblk clr @errnum ; clear last disk error 291 68F2 A038 292 68F4 C034 mov *stack+,r0 ; length of file name 293 68F6 C074 mov *stack+,r1 ; address of filename 294 68F8 C1B4 mov *stack+,r6 ; pop number of kilobytes 295 68FA 06C0 swpb r0 ; get file name length in MSB 296 68FC D800 movb r0,@pabnln ; load name length byte in CPU PAB 296 68FE A189 297 6900 06C0 swpb r0 298 ; check size against limits... 299 6902 0286 ci r6,1 ; minimum size 299 6904 0001 300 6906 1104 jlt toosml ; size is too small, force to 1 301 6908 0286 ci r6,1024 ; maximum size 301 690A 0400 302 690C 1504 jgt toobig ; size is too big, force to 1024 303 690E 1005 jmp cont 304 6910 0206 toosml li r6,1 ; force size to 1 304 6912 0001 305 6914 1002 jmp cont ; continue 306 6916 0206 toobig li r6,1024 ; force size to 1024 306 6918 0400 307 ; copy the filename into the cpu ram PAB... 308 691A 0202 cont li r2,pabfil ; address of filename in CPU PAB 308 691C A18A 309 691E DCB1 mkdskl movb *r1+,*r2+ ; copy character of filename 310 6920 0600 dec r0 ; finished copying filename? 311 6922 16FD jne mkdskl 312 ; create a 128 byte block of space characters in vdp ram 313 6924 0200 li r0,recbuf ; vdp target address 313 6926 1BA0 314 6928 C800 mov r0,@pabbuf ; set vdp source buffer address 314 692A A182 315 692C 0201 li r1,>2000 ; space character 315 692E 2000 316 6930 0202 li r2,128 ; 128 bytes to write 316 6932 0080 317 6934 06A0 bl @vsbwmi ; write bytes 317 6936 7880 318 ; put the pab into vdp ram, with an open opcode. open the file, dis/fix 128 319 6938 0201 li r1,>8000 ; logical record length: 128 bytes (in msb) 319 693A 8000 320 693C D801 movb r1,@pablrl ; set logical record length 320 693E A184 321 6940 04E0 clr @pabrec ; set record number to 0 321 6942 A186 322 6944 06A0 bl @diskio 322 6946 69B8 323 6948 0003 byte open,3 ; dis/fix output 324 694A 1312 jeq mkderr ; jump if error 325 ; the file should be created at this point. now write a record: 326 ; the number of kilobytes to create is in r6 327 694C 0207 next1k li r7,8 ; number of records for 1k. 8x128 bytes=1024 327 694E 0008 328 6950 06A0 nxtrec bl @diskio ; write the pab to vdp 328 6952 69B8 329 6954 0303 byte write,3 ; dis/fix output 330 6956 130C jeq mkderr ; jump if error 331 6958 05A0 inc @pabrec ; increment record number 331 695A A186 332 695C 0607 dec r7 ; decrement record counter 333 695E 16F8 jne nxtrec ; repeat if we haven't written 8 records 334 6960 0606 dec r6 ; decrement kilobyte counter 335 6962 16F4 jne next1k ; repeat if not finished 336 ; close the file 337 6964 06A0 mkclse bl @diskio ; write the pab to vdp 337 6966 69B8 338 6968 0103 byte close,3 ; dis/fix output 339 696A 06A0 bl @rstsp ; restore code in scratchpad 339 696C 6AEE 340 ; (destroyed by DSR access) 341 696E 10B6 jmp bufxit 342 ; something went wrong... 343 6970 06C0 mkderr swpb r0 344 6972 C800 mov r0,@errnum ; set disk io error number 344 6974 A038 345 6976 10F6 jmp mkclse ; close file (for what it's worth) and exit 346 ;] 347 348 ;[ compute block address routine 349 ; given buffer number on the stack, gives address of appropriate blk in r0 350 ; and the associated vdp address in r1 351 ; Used by CLEAN, DIRTY, and DIRTY? 352 6978 C034 cba mov *stack+,r0 ; get blk number 353 697A 0A20 sla r0,2 ; convert to offset 354 697C 0201 li r1,blk0 ; address of first blk 354 697E A1B6 355 6980 A001 a r1,r0 ; get address of blk 356 6982 05C0 inct r0 ; point to vdp address pointer 357 6984 C050 mov *r0,r1 ; get vdp address 358 6986 045B rt ; return to caller 359 ;] 360 361 ;[ Free Buffer subroutine. Scans for a free buffer. 362 ; Returns a free blk address in r0. 363 ; r0=0 means there are no free buffers 364 ; a buffer will treated as free if it's dirty flag is not set 365 6988 C0A0 frebuf mov @totblk,r2 ; number of buffers to check 365 698A A1B0 366 698C 0200 li r0,blk0 ; buffer status pointer for 1st buffer 366 698E A1B6 367 6990 C050 nxtfb mov *r0,r1 ; check block assignment 368 6992 1305 jeq bfree ; jump if buffer is free 369 6994 0220 ai r0,4 ; point to next blk 369 6996 0004 370 6998 0602 dec r2 ; finished? 371 699A 16FA jne nxtfb ; check again if not 372 699C 04C0 clr r0 ; there are no free buffers 373 699E 045B bfree rt 374 ;] 375 376 ;[ scan buffers to see if the block in question is already in memory 377 ; expects block number in r0 378 ; returns address of blk in r1, or 0 if the block is not in memory 379 69A0 0201 scnblk li r1,blk0 ; address of first buffer 379 69A2 A1B6 380 69A4 C0A0 mov @totblk,r2 ; number of buffers to check 380 69A6 A1B0 381 69A8 8440 scnnxt c r0,*r1 ; is this the block we're looking for? 382 69AA 1305 jeq fndblk ; jump if yes 383 69AC 0221 ai r1,4 ; check next buffer 383 69AE 0004 384 69B0 0602 dec r2 ; finished? 385 69B2 16FA jne scnnxt ; repeat if not 386 69B4 04C1 clr r1 ; not in memory 387 69B6 045B fndblk rt 388 ;] 389 390 ;[ put the pab into vdp ram with the appropriate opcode in byte 0 of pab 391 ; then call dos... 392 69B8 C83B diskio mov *r11+,@pabopc ; load opcode and file format into ram pab 392 69BA A180 393 69BC C28B mov r11,r10 ; save return address, as BL below will 394 ; destroy it 395 69BE 0201 li r1,pabloc+9 ; vdp address of name length byte 395 69C0 1B81 396 69C2 C801 mov r1,@namptr ; move it to >8356 as per DSR requirements 396 69C4 8356 397 ; write the PAB into VDP ram... 398 69C6 0200 li r0,pabloc ; vdp destination 398 69C8 1B78 399 69CA 0201 li r1,pabopc ; source 399 69CC A180 400 69CE 0202 li r2,30 ; number of bytes to copy to vdp 400 69D0 001E 401 69D2 06A0 bl @_vmbw0 ; write the pab to vdp 401 69D4 7854 402 69D6 0420 blwp @dsrlnk ; call dos 402 69D8 69DE 403 69DA 0008 data 8 ; disk op parameter, level 3 command 404 69DC 045A b *r10 405 ;] 406 407 ;[ dsr link routine - Written by Paolo Bagnaresi 408 69DE A156 dsrlnk data dsrlws ; dsrlnk workspace 409 69E0 69E2 data dlentr ; entry point 410 411 dlentr ; li r0,>37d7 412 ; mov r0,@>8370 413 69E2 0200 li r0,>aa00 413 69E4 AA00 414 69E6 D800 movb r0,@haa ; load haa 414 69E8 A176 415 69EA C17E mov *r14+,r5 ; get pgm type for link 416 69EC C805 mov r5,@sav8a ; save data following blwp @dsrlnk (8 or >a) 416 69EE A148 417 69F0 53E0 szcb @h20,r15 ; reset equal bit 417 69F2 6AEC 418 69F4 C020 mov @>8356,r0 ; get ptr to pab 418 69F6 8356 419 69F8 C240 mov r0,r9 ; save ptr 420 69FA C800 mov r0,@flgptr ; save again pointer to pab+1 for dsrlnk 420 69FC A154 421 ; data 8 422 69FE 0229 ai r9,>fff8 ; adjust to flag 422 6A00 FFF8 423 6A02 06A0 bl @_vsbr ; read device name length 423 6A04 77E4 424 6A06 D0C1 movb r1,r3 ; copy it 425 6A08 0983 srl r3,8 ; make it lo byter 426 6A0A 0704 seto r4 ; init counter 427 6A0C 0202 li r2,namsto ; point to buffer 427 6A0E A178 428 6A10 0580 lnkslp inc r0 ; point to next char of name 429 6A12 0584 inc r4 ; incr char counter 430 6A14 0284 ci r4,>0007 ; see if length more than 7 chars 430 6A16 0007 431 6A18 1561 jgt lnkerr ; yes, error 432 6A1A 80C4 c r4,r3 ; end of name? 433 6A1C 1306 jeq lnksln ; yes 434 6A1E 06A0 bl @_vsbr ; read curr char 434 6A20 77E4 435 6A22 DC81 movb r1,*r2+ ; move into buffer 436 6A24 9801 cb r1,@decmal ; is it a period? 436 6A26 6AEA 437 6A28 16F3 jne lnkslp ; no 438 6A2A C104 lnksln mov r4,r4 ; see if 0 length 439 6A2C 1357 jeq lnkerr ; yes, error 440 6A2E 04E0 clr @>83d0 440 6A30 83D0 441 6A32 C804 mov r4,@>8354 ; save name length for search 441 6A34 8354 442 6A36 C804 mov r4,@savlen ; save it here too 442 6A38 A14E 443 6A3A 0584 inc r4 ; adjust for period 444 6A3C A804 a r4,@>8356 ; point to position after name 444 6A3E 8356 445 6A40 C820 mov @>8356,@savpab ; save pointer to position after name 445 6A42 8356 445 6A44 A150 446 6A46 02E0 srom lwpi >83e0 ; use gplws 446 6A48 83E0 447 6A4A 04C1 clr r1 ; version found of dsr 448 6A4C 020C li r12,>0f00 ; init cru addr 448 6A4E 0F00 449 6A50 C30C norom mov r12,r12 ; anything to turn off? 450 6A52 1301 jeq nooff ; no 451 6A54 1E00 sbz 0 ; yes, turn off 452 6A56 022C nooff ai r12,>0100 ; next rom to turn on 452 6A58 0100 453 6A5A 04E0 clr @>83d0 ; clear in case we are done 453 6A5C 83D0 454 6A5E 028C ci r12,>2000 ; see if done 454 6A60 2000 455 6A62 133A jeq nodsr ; yes, no dsr match 456 6A64 C80C mov r12,@>83d0 ; save addr of next cru 456 6A66 83D0 457 6A68 1D00 sbo 0 ; turn on rom 458 6A6A 0202 li r2,>4000 ; start at beginning of rom 458 6A6C 4000 459 6A6E 9812 cb *r2,@haa ; check for a valid rom 459 6A70 A176 460 6A72 16EE jne norom ; no rom here 461 6A74 A0A0 a @dstype,r2 ; go to first pointer 461 6A76 A160 462 6A78 1003 jmp sgo2 463 6A7A C0A0 sgo mov @>83d2,r2 ; continue where we left off 463 6A7C 83D2 464 6A7E 1D00 sbo 0 ; turn rom back on 465 6A80 C092 sgo2 mov *r2,r2 ; is addr a zero (end of link) 466 6A82 13E6 jeq norom ; yes, no programs to check 467 6A84 C802 mov r2,@>83d2 ; remember where to go next 467 6A86 83D2 468 6A88 05C2 inct r2 ; go to entry point 469 6A8A C272 mov *r2+,r9 ; get entry addr just in case 470 6A8C D160 movb @>8355,r5 ; get length as counter 470 6A8E 8355 471 6A90 1309 jeq namtwo ; if zero, do not check 472 6A92 9C85 cb r5,*r2+ ; see if length matches 473 6A94 16F2 jne sgo ; no, try next 474 6A96 0985 srl r5,8 ; yes, move to lo byte as counter 475 6A98 0206 li r6,namsto ; point to buffer 475 6A9A A178 476 6A9C 9CB6 namone cb *r6+,*r2+ ; compare buffer with rom 477 6A9E 16ED jne sgo ; try next if no match 478 6AA0 0605 dec r5 ; loop til full length checked 479 6AA2 16FC jne namone 480 6AA4 0581 namtwo inc r1 ; next version found 481 6AA6 C801 mov r1,@savver ; save version 481 6AA8 A152 482 6AAA C809 mov r9,@savent ; save entry addr 482 6AAC A14C 483 6AAE C80C mov r12,@savcru ; save cru 483 6AB0 A14A 484 6AB2 0699 bl *r9 ; go run routine 485 6AB4 10E2 jmp sgo ; error return 486 6AB6 1E00 sbz 0 ; turn off rom if good return 487 6AB8 02E0 lwpi dsrlws ; restore workspace 487 6ABA A156 488 6ABC C009 mov r9,r0 ; point to flag in pab 489 6ABE C060 frmdsr mov @sav8a,r1 ; get back data following blwp @dsrlnk 489 6AC0 A148 490 ; (8 or >a) 491 6AC2 0281 ci r1,8 ; was it 8? 491 6AC4 0008 492 6AC6 1303 jeq dsrdt8 ; yes, jump: normal dsrlnk 493 6AC8 D060 movb @>8350,r1 ; no, we have a data >a. get error byte from 493 6ACA 8350 494 ; >8350 495 6ACC 1002 jmp dsrdta ; go and return error byte to the caller 496 6ACE 06A0 dsrdt8 bl @_vsbr ; read flag 496 6AD0 77E4 497 6AD2 09D1 dsrdta srl r1,13 ; just keep error bits 498 6AD4 1604 jne ioerr ; handle error 499 6AD6 0380 rtwp 500 6AD8 02E0 nodsr lwpi dsrlws ; no dsr, restore workspace 500 6ADA A156 501 6ADC 04C1 lnkerr clr r1 ; clear flag for error 0 = bad device name 502 6ADE 06C1 ioerr swpb r1 ; put error in hi byte 503 6AE0 D741 movb r1,*r13 ; store error flags in callers r0 504 6AE2 F3E0 socb @h20,r15 ; set equal bit to indicate error 504 6AE4 6AEC 505 6AE6 0380 rtwp 506 507 6AE8 0008 data8 data >8 ; just to compare. 8 is the data that 508 ; usually follows a blwp @dsrlnk 509 6AEA 2E decmal text '.' ; for finding end of device name 510 6AEB 0000 even 511 6AEC 2000 h20 data >2000 512 ;] 513 514 ;[ restore code to scratch-pad ram 515 ; accessing the disk via the disk DSR destroys some code in scratch pad 516 ; restore the code in scratch pad before returning 517 6AEE 0200 rstsp li r0,toram ; address of 1st source block 517 6AF0 7EB8 518 6AF2 0201 li r1,docol ; destination 518 6AF4 8320 519 6AF6 CC70 rstsp1 mov *r0+,*r1+ ; copy a cell 520 6AF8 0280 ci r0,__dup 520 6AFA 7F06 521 6AFC 1602 jne rstsp3 522 6AFE 0201 li r1,_dup 522 6B00 8382 523 6B02 0280 rstsp3 ci r0,padend ; hit end of first block of code? 523 6B04 7F44 524 6B06 16F7 jne rstsp1 ; loop if not 525 6B08 045B rt 526 ;] * * COPY 'C:\TI\Source\TurboForth\Bank1\1-07-Double.a99' * 1 2 ; Double Number Words - removed and included in the 32-bit library 3 4 ;[ 2DROP ( d -- ) 5 ;_drop2 dect stack ; move back up the stack 4 bytes 6 ; dect stack 7 ;drop2x b @retB0 8 ;] 9 10 ;[ 2DUP ( d -- d d ) 11 6B0A C914 _dup2 mov *stack,@-4(stack) ; copy tos 11 6B0C FFFC 12 6B0E 0644 dect stack 13 6B10 C524 mov @4(stack),*stack 13 6B12 0004 14 6B14 0644 dect stack 15 6B16 0460 b @retB0 15 6B18 833A 16 ;] 17 * * COPY 'C:\TI\Source\TurboForth\Bank1\1-08-Parsing.a99' * 1 ; _____ _ __ __ _ 2 ; | __ \ (_) \ \ / / | | 3 ; | |__) |__ _ _ __ ___ _ _ __ __ _ \ \ /\ / /___ _ __ __| |___ 4 ; | ___// _` | '__/ __| | '_ \ / _` | \ \/ \/ // _ \| '__/ _` / __| 5 ; | | | (_| | | \__ \ | | | | (_| | \ /\ /| (_) | | | (_| \__ \ 6 ; |_| \__,_|_| |___/_|_| |_|\__, | \/ \/ \___/|_| \__,_|___/ 7 ; __/ | 8 ; |___/ 9 ; Dictionary lookup and associated parsing words 10 11 ;[ WORD ( delimiter address -- address length ) 12 ; 13 ; Moves through TIB in VDP memory, discarding leading delimiters, 14 ; looking for a word. A word is identified when a trailing delimiter is 15 ; detected. The identified word is copied from VDP to a buffer in CPU memory. 16 ; Pushes the start address of the word (in CPU memory), and the length of 17 ; the word to the stack. If no word is found (for example if we hit the 18 ; end of the TIB without detecting a word then 0 0 is pushed on the 19 ; stack. 20 6B1A C014 _word mov *stack,r0 ; buffer address 21 6B1C A020 a @in,r0 ; add offset 21 6B1E A042 22 6B20 C0A4 mov @2(stack),r2 ; delimeter 22 6B22 0002 23 6B24 0A82 sla r2,8 ; move to high-byte 24 6B26 0206 li r6,wrdbuf+1 ; address of cpu word buffer 24 6B28 A1D1 25 6B2A C906 mov r6,@2(stack) ; push it to stack 25 6B2C 0002 26 6B2E 04C8 clr r8 ; length counter 27 6B30 C1E0 mov @_span,r7 ; number of chars in buffer 27 6B32 A04C 28 6B34 131F jeq noword ; if 0 then there's no word 29 6B36 8820 c @in,@_span ; hit end of buffer? 29 6B38 A042 29 6B3A A04C 30 6B3C 141B jhe noword ; if yes then exit 31 32 6B3E 06A0 wrd1 bl @wrdgb ; read a character and advance along input 32 6B40 6B86 33 6B42 05A0 inc @in ; advance >IN 33 6B44 A042 34 6B46 9081 cb r1,r2 ; was the character a delimiter? 35 6B48 13FA jeq wrd1 ; if yes then get another character 36 6B4A 8820 c @in,@_span ; hit end of buffer? 36 6B4C A042 36 6B4E A04C 37 6B50 150F jgt wrdfin ; if yes then quit 38 6B52 DD81 wrd2 movb r1,*r6+ ; move character to word buffer 39 6B54 0588 inc r8 ; increment length 40 6B56 8808 c r8,@tibsiz ; have we fully populated the word buffer? 40 6B58 A04A 41 6B5A 130A jeq wrdfin ; if yes then exit 42 6B5C 06A0 bl @wrdgb ; read a character and advance along input 42 6B5E 6B86 43 6B60 05A0 inc @in ; advance >in 43 6B62 A042 44 6B64 8820 c @in,@_span ; hit end of buffer? 44 6B66 A042 44 6B68 A04C 45 6B6A 1502 jgt wrdfin ; if yes then quit 46 6B6C 9081 cb r1,r2 ; was the character a delimeter? 47 6B6E 16F1 jne wrd2 ; if not then get another character 48 6B70 C508 wrdfin mov r8,*stack ; push length to stack 49 6B72 1004 jmp wrdxit1 ; exit 50 6B74 04D4 noword clr *stack ; no word found, push 0 length 51 6B76 04E4 clr @2(stack) ; zero address 51 6B78 0002 52 6B7A 04C8 clr r8 53 6B7C 06C8 wrdxit1 swpb r8 ; populate length byte (for packed string) 54 6B7E D808 movb r8,@wrdbuf 54 6B80 A1D0 55 6B82 0460 wrdxit2 b @retB0 55 6B84 833A 56 57 6B86 C3E0 wrdgb mov @source,r15 ; check source 57 6B88 A058 58 6B8A 1302 jeq vread ; if 0 then read from vdp 59 ; special case: if EVALUATE is active then the evaluation string will be in 60 ; CPU RAM 61 6B8C D070 movb *r0+,r1 ; otherwise read from cpu and advance buffer 62 6B8E 045B rt ; return to caller 63 6B90 C38B vread mov r11,r14 ; save return address 64 6B92 06A0 vread1 bl @_vsbr ; read from vdp 64 6B94 77E4 65 6B96 0580 vread2 inc r0 ; advance input buffer address 66 6B98 045E b *r14 ; return to caller 67 ;] 68 69 ;[ code for processing \ type comments 70 ; assembly equivalent of : \ >IN @ 64 + -64 AND >IN ! ; IMMEDIATE 71 6B9A C020 _trcom mov @blknum,r0 ; loading a block? 71 6B9C A1B2 72 6B9E 1309 jeq trcom1 ; jump if not 73 6BA0 C020 mov @in,r0 73 6BA2 A042 74 6BA4 0220 ai r0,64 74 6BA6 0040 75 6BA8 0240 andi r0,-64 75 6BAA FFC0 76 6BAC C800 mov r0,@in 76 6BAE A042 77 6BB0 10E8 jmp wrdxit2 ; exit (jump is smaller than a branch!) 78 6BB2 C820 trcom1 mov @tibsiz,@in ; set >IN to the end of the line 78 6BB4 A04A 78 6BB6 A042 79 6BB8 10E4 comxit jmp wrdxit2 ; exit (jump is smaller than a branch!) 80 ;] 81 82 ;[ NUMBER ( address length -- (numberMSW) numberLSW error ) 83 ; Attempts to convert the string at cpu address address into a number. 84 ; If fully successful, the number is placed on the stack and flag will be 0. 85 ; If it fails (for example contains an illegal character) then a partial number 86 ; will be placed on the stack (the value computed up until the failure) and 87 ; flag will be >0. 88 ; Thus, if flag>0 the string failed to parse fully as a number. 89 ; A minus sign is permitted for negative numbers. 90 ; This routine uses BASE to parse numbers in the current BASE. 91 ; Eg. If BASE=16 then digits 0-9 and A-F are considered legal and will be 92 ; parsed properly. 93 ; A facility also exists called 'quick hex' that allows a number to be entered 94 ; in base 16, by placing a $ symbol at the beginning of the string. This avoids 95 ; the need to change BASE to enter a number. E.g. instead of HEX FEED DECIMAL 96 ; you can simply do $FEED. The number will be parsed as a HEX number without the 97 ; need to change BASE. 98 ; The same facility also exists for binary numbers: use a % symbol. 99 ; E.g. %1001 = 9 decimal 100 ; The numbers returned are (by default) singles (16 bits). NUMBER can can also 101 ; return a double (32-bit (2 stack cells)) value by including a period in the 102 ; number string. E.g. 100. 1.00 10.0 .100 will all return 100 decimal as a 103 ; double. 104 ; The various facilities can be mixed. For example, -$.F means -15 as a double. 105 6BBA C074 _numbr mov *stack+,r1 ; pop length 106 6BBC C014 mov *stack,r0 ; get address from stack 107 ; parse the number string... 108 6BBE 04C6 parsnm clr r6 ; initialise MSW 109 6BC0 04C8 clr r8 ; initialise LSW 110 6BC2 04CD clr r13 ; clear negative flag 111 6BC4 04CC clr r12 ; clear 'double required' flag 112 6BC6 0720 seto @dpl ; assume single precision 112 6BC8 A054 113 ; begin ugly hack - check the end of the number for a period character 114 ; if found, set double indicator (R12) to on and reduce length of string 115 ; by 1. Added for TF V1.1 double precision library support 116 6BCA C3C0 mov r0,r15 ; copy string address 117 6BCC A001 a r1,0 ; add length 118 6BCE 0600 dec r0 ; point to last character in the buffer 119 6BD0 D0B0 movb *r0+,r2 ; get character from buffer 120 6BD2 0982 srl r2,8 ; move it to low byte 121 6BD4 0282 ci r2,'.' ; is it a period character? 121 6BD6 002E 122 6BD8 1604 jne xugly ; if not then skip 123 6BDA 070C seto r12 ; otherwise set the double flag to on 124 6BDC 0601 dec r1 ; and reduce the length for the string so 125 ; that the period will not be seen by the 126 ; number parser 127 6BDE 0720 seto @dpl ; double integer 127 6BE0 A054 128 ; end ugly hack 129 6BE2 C00F xugly mov r15,r0 130 6BE4 C3A0 mov @base,r14 ; get base 130 6BE6 A05C 131 6BE8 060E dec r14 ; base-1=highest legal digital for base 132 6BEA D0B0 num0 movb *r0+,r2 ; get character from buffer 133 6BEC 0982 srl r2,8 ; move it to low byte 134 6BEE 0282 num4 ci r2,'%' ; is it a % sign (binary) 134 6BF0 0025 135 6BF2 1603 jne num5 136 6BF4 020E li r14,1 ; set binary base 136 6BF6 0001 137 6BF8 1017 jmp num3 ; do next character 138 6BFA 0282 num5 ci r2,'.' ; is it a dot? 138 6BFC 002E 139 6BFE 160A jne num1 ; skip if not 140 ; double detected - set r12 as flag, and calculate value for DPL 141 6C00 070C seto r12 ; else double is required - set flag 142 6C02 C3E4 mov @2(stack),r15 ; get string length 142 6C04 0002 143 6C06 C1CF mov r15,r7 ; 144 6C08 61C1 s r1,r7 ; subtract current position from length 145 6C0A 63C7 s r7,r15 ; get length to the right of the dec. point 146 6C0C 060F dec r15 ; correcty length due to decimal point 147 6C0E C80F mov r15,@dpl ; store in DPL 147 6C10 A054 148 6C12 100A jmp num3 ; do next character 149 6C14 0282 num1 ci r2,'$' ; is it a dollar sign? 149 6C16 0024 150 6C18 1603 jne num2 ; skip if not 151 6C1A 020E li r14,15 ; force base temporarily to 16-1 for hex 151 6C1C 000F 152 6C1E 1004 jmp num3 ; check next character 153 6C20 0282 num2 ci r2,'-' ; is it a negative sign? 153 6C22 002D 154 6C24 1603 jne numlz ; skip if not 155 6C26 070D seto r13 ; else set negative flag 156 6C28 0601 num3 dec r1 ; decrement counter 157 6C2A 10DF jmp num0 ; get next character 158 6C2C 0282 numlz ci r2,'0' ; check if ascii code < "0" 158 6C2E 0030 159 6C30 1A09 jl ohshit ; error if yes 160 6C32 0282 ci r2,'Z' ; check if ascii code > "Z" 160 6C34 005A 161 6C36 1B06 jh ohshit ; error if yes 162 6C38 0282 ci r2,'9' ; check if ascii code <= "9" 162 6C3A 0039 163 6C3C 1209 jle numisd ; its a numerical digit between 0-9 164 6C3E 0282 ci r2,'A' ; check if ascii code >= "A" 164 6C40 0041 165 6C42 1403 jhe numisl ; its a letter between A-Z 166 6C44 0200 ohshit li r0,2 ; else illegal digit was detected 166 6C46 0002 167 ; indicate error 168 6C48 1018 jmp nexit 169 6C4A 0222 numisl ai r2,-55 ; convert from letter to number 169 6C4C FFC9 170 ; ("A" (65) becomes 10) 171 6C4E 1002 jmp numgo ; start the conversion 172 6C50 0222 numisd ai r2,-48 ; convert from ascii to decimal 172 6C52 FFD0 173 ; ("0" (48) becomes 0) 174 ; parse the string into a 32 bit number... 175 6C54 8382 numgo c r2,r14 ; compare to base 176 6C56 1BF6 jh ohshit ; if digit outside current base's legal 177 ; range then exit 178 6C58 A202 a r2,r8 ; add digit to LSW 179 6C5A 0601 dec r1 ; finished? 180 6C5C 1309 jeq numend ; jump if yes 181 6C5E C08E mov r14,r2 ; base-1 to r2 182 6C60 0582 inc r2 ; correct to base 183 6C62 C1C8 mov r8,r7 ; get our lsw in r7 184 6C64 39C2 mpy r2,r7 ; multiply it by current base 185 6C66 C246 mov r6,r9 ; get our MSW 186 6C68 3A42 mpy r2,r9 ; multiply it by current base 187 6C6A C18A mov r10,r6 ; move it back 188 6C6C A187 a r7,r6 ; add MSW from MPY to *our* MSW 189 6C6E 10BD jmp num0 ; do next digit 190 6C70 04C0 numend clr r0 ; finished with no errors, clear error flag 191 6C72 C34D mov r13,r13 ; and check negative flag 192 6C74 1302 jeq nexit ; jump if not set (positive number) 193 6C76 0546 inv r6 ; else two's complement the 32 bit word 194 6C78 0508 neg r8 195 6C7A C508 nexit mov r8,*stack ; push least sig word 196 6C7C 0644 dect stack ; advance stack 197 6C7E C80C mov r12,@isdbl ; was a double returned? 197 6C80 A052 198 6C82 1302 jeq pusher ; if not, skip 199 6C84 C506 mov r6,*stack ; push most sig word 200 6C86 0644 dect stack ; advance stack 201 6C88 C500 pusher mov r0,*stack ; push error flag 202 6C8A 020C li r12,_next ; restore r12 202 6C8C 8326 203 6C8E 1094 jmp comxit ; exit 204 ; (a jump is 2 bytes shorter than a branch) 205 ;] 206 207 6C90 2000 _space data >2000 * * COPY 'C:\TI\Source\TurboForth\Bank1\1-09-Compilation.a99' * 1 ; _____ _ _ _ __ __ _ 2 ; / ____| (_) (_) \ \ / / | | 3 ; | | ___ _ __ ___ _ __ _| |_ _ __ __ _ \ \ /\ / /___ _ __ __| |___ 4 ; | | / _ \| '_ ` _ \| '_ \| | | | '_ \ / _` | \ \/ \/ // _ \| '__/ _` / __| 5 ; | |____| (_) | | | | | | |_) | | | | | | | (_| | \ /\ /| (_) | | | (_| \__ \ 6 ; \_____|\___/|_| |_| |_| .__/|_|_|_|_| |_|\__, | \/ \/ \___/|_| \__,_|___/ 7 ; | | __/ | 8 ; |_| |___/ 9 ; Compilation words... 10 11 ;[ HEADER ( address length -- ) 12 ; creates a dictionary entry starting at HERE, and links it to the previous 13 ; dictionary entry. 14 6C92 C074 _headr mov *stack+,r1 ; length in r1 15 6C94 0241 andi r1,15 ; restrict length to 15 15 6C96 000F 16 6C98 C181 hdr0 mov r1,r6 ; copy length of word to use as a counter 17 ; mov @blknum,r0 ; get 'are we loading?' flag 18 6C9A C020 mov @lstblk,r0 ; get 'are we loading?' flag 18 6C9C A1B4 19 6C9E 1303 jeq hdr1 ; if not then skip 20 6CA0 0600 dec r0 ; decrement by 1 to give room for 0 to 1023 21 6CA2 0A40 sla r0,4 ; shift into position 22 6CA4 E040 soc r0,r1 ; OR into length word 23 6CA6 C034 hdr1 mov *stack+,r0 ; pop address of word to r0 24 6CA8 C0A0 mov @here,r2 ; here to r2 24 6CAA A046 25 6CAC C4A0 mov @latest,*r2 ; create link to previous dictionary entry 25 6CAE A044 26 6CB0 C802 mov r2,@latest ; update latest to point to this entry 26 6CB2 A044 27 6CB4 05C2 inct r2 ; move forward in memory 28 6CB6 CC81 mov r1,*r2+ ; append length of word to dictionary entry 29 6CB8 DCB0 crtlp movb *r0+,*r2+ ; get a character 30 6CBA 0606 dec r6 ; finished copying name? 31 6CBC 16FD jne crtlp ; repeat if not 32 6CBE 0582 inc r2 ; we're gonna force r2 to an even address... 33 6CC0 0242 andi r2,>fffe ; force to even address 33 6CC2 FFFE 34 6CC4 C802 mov r2,@here ; update here 34 6CC6 A046 35 6CC8 C802 mov r2,@patch ; update most recent CFA locaation 35 6CCA A06A 36 6CCC C002 mov r2,r0 ; copy to r0 for memory pointer adjust rtn. 37 6CCE 1005 jmp mpadj ; update memory free pointers and exit 38 ;] 39 40 ;[ , (COMMA) ( value -- ) 41 ; appends 16 bit word on TOS to the user memory addressed by HERE and updates 42 ; HERE to point to next word 43 6CD0 C020 _comma mov @here,r0 ; get next free address in r0 43 6CD2 A046 44 6CD4 CC34 mov *stack+,*r0+ ; pop value to HERE 45 6CD6 C800 mov r0,@here ; update HERE 45 6CD8 A046 46 6CDA 0280 mpadj ci r0,>a000 ; are we in high memory? 46 6CDC A000 47 6CDE 1A03 jl lomadj ; no, take the jump 48 6CE0 C800 mov r0,@ffaihm ; we must be writing in low ram. update low 48 6CE2 A01C 49 ; mem pointer 50 6CE4 1002 jmp commax 51 6CE6 C800 lomadj mov r0,@ffailm ; update high memory pointer 51 6CE8 A01A 52 6CEA 0460 commax b @retB0 52 6CEC 833A 53 ;] 54 55 ;[ C, (COMMA) ( value -- ) 56 ; appends an 8 bit value, from the least significant byte of TOS to HERE. 57 ; Here is incremented by ONE BYTE, not one WORD. 58 ; For safety, use ALIGN to align HERE to a word boundary afterwards. 59 6CEE C020 _comab mov @here,r0 ; get next free address in r0 59 6CF0 A046 60 6CF2 C074 mov *stack+,r1 ; get stack value in r1 61 6CF4 06C1 swpb r1 ; get TOS in most significant byte 62 6CF6 DC01 movb r1,*r0+ ; mov data in TOS to HERE and increment by 63 ; one byte 64 6CF8 C800 mov r0,@here ; update HERE 64 6CFA A046 65 6CFC 10EE jmp mpadj ; update memory pointers 66 ;] 67 68 ;[ ALIGN ( -- ) 69 ; Aligns HERE to an even word boundary by rounding up if required 70 ; Call it after using C! 71 6CFE C020 _align mov @here,r0 ; get HERE 71 6D00 A046 72 6D02 0580 inc r0 ; add 1 73 6D04 0240 andi r0,>fffe ; round up if required 73 6D06 FFFE 74 6D08 C800 mov r0,@here ; store it 74 6D0A A046 75 6D0C 10E6 jmp mpadj ; update memory pointers 76 ;] 77 78 ;[ HIDDEN ( dictionary_address -- ) 79 ; toggles the hidden attribute on the dictionary entry 80 ; normally you would hide a word after defining it with: LATEST @ HIDDEN 81 6D0E C034 _hide mov *stack+,r0 ; pop address of dictionary entry to r0 82 6D10 05C0 inct r0 ; point to length entry 83 6D12 C050 mov *r0,r1 ; get the length entry 84 6D14 2860 xor @_bit1,r1 ; toggle hidden bit (weight >4000) 84 6D16 78B6 85 6D18 C401 mov r1,*r0 ; store it 86 6D1A 10E7 jmp commax 87 ;] 88 89 ;[ IMMEDIATE ( -- ) 90 ; toggles the immediate bit in the dictionary entry pointed to by LATEST. 91 6D1C C020 _imm mov @latest,r0 ; get address of latest dictionary entry 91 6D1E A044 92 6D20 05C0 inct r0 ; point to length entry 93 6D22 C050 mov *r0,r1 ; get the length entry 94 6D24 2860 xor @_bit0,r1 ; toggle immediate bit (weight >8000) 94 6D26 78B4 95 6D28 C401 mov r1,*r0 ; store it 96 6D2A 10DF jmp commax 97 ;] 98 99 ;[ ALLOT ( n -- ) 100 ; reserves n BYTES of memory, staring from HERE 101 6D2C A834 _allot a *stack+,@here ; pop and add n to HERE 101 6D2E A046 102 6D30 C020 mov @here,r0 ; get HERE in r0 for mpadj routine 102 6D32 A046 103 6D34 10D2 jmp mpadj ; adjust memory pointers 104 ;] 105 106 ;[ COMPILE ( -- ) 107 ; Used in colon definitiona. Compiles the next word into the current definition 108 ; the word is not executed. E.g. COMPILE DROP compiles DROP to HERE. DROP is not 109 ; actually executed 110 ; important note: see COMPILE in 0-10-Compilation.a99 111 6D36 C020 _compil mov @here,r0 ; get HERE 111 6D38 A046 112 6D3A CC01 mov r1,*r0+ ; compile next word to HERE & increase HERE 113 6D3C C800 mov r0,@here ; save HERE 113 6D3E A046 114 6D40 10CC jmp mpadj ; adjust memory pointers 115 ;] * * COPY 'C:\TI\Source\TurboForth\Bank1\1-10-Strings.a99' * 1 ; _____ _ _ __ __ _ 2 ; / ____| | (_) \ \ / / | | 3 ; | (___ | |_ _ __ _ _ __ __ _ \ \ /\ / /___ _ __ __| |___ 4 ; \___ \| __| '__| | '_ \ / _` | \ \/ \/ // _ \| '__/ _` / __| 5 ; ____) | |_| | | | | | | (_| | \ /\ /| (_) | | | (_| \__ \ 6 ; |_____/ \__|_| |_|_| |_|\__, | \/ \/ \___/|_| \__,_|___/ 7 ; string related words __/ | 8 ; |___/ 9 10 ;[ RND ( limit -- n) 11 ; pushes a pseudo random number between 0 and limit-1 (rnd MOD limit) 12 ; For the full range (0-65535) use a limit of 0 13 6D42 C060 _rnd mov @seed,r1 13 6D44 A076 14 6D46 0200 li r0,>6fe5 ; multiplier 14 6D48 6FE5 15 6D4A 3840 mpy r0,r1 ; mpultiply r1 by r0 16 6D4C 0222 ai r2,>7ab9 ; add 7ab9 to r2 16 6D4E 7AB9 17 6D50 0B52 src r2,5 ; rotate r2 5 bits right 18 6D52 C802 mov r2,@seed 18 6D54 A076 19 6D56 04C1 clr r1 ; msw of dividend 20 6D58 3C54 div *stack,r1 ; divide R1 by # on stack 21 6D5A C502 mov r2,*stack ; copy remainder, R2, to stack 22 6D5C 0460 rndx b @retb0 22 6D5E 833A 23 ;] 24 25 ;[ COUNT ( addr1 -- addr2 len ) 26 ; addr2 is addr1+1 and len is the length of the counted string at addr1. 27 ; The byte at addr1 contains the byte count len. Range of len is {0.255} 28 6D60 C014 _count mov *stack,r0 ; get addr1 29 6D62 D1D0 movb *r0,r7 ; get length byte from addr1 30 6D64 0987 srl r7,8 ; move to low byte 31 6D66 0594 inc *stack ; increment addr1 to make addr2 32 6D68 0644 PAE dect stack ; make space on stack 33 6D6A C507 mov r7,*stack ; push length 34 6D6C 10F7 jmp rndx 35 ;] 36 37 ;[ -TRAILING ( addr len -- addr len ) 38 ; modifies len such that trailing spaces are excluded from the string 39 6D6E C514 _trail mov *stack,*stack ; check length 40 6D70 1308 jeq trlout ; if 0 then exit 41 6D72 1107 jlt trlout ; if negative then exit 42 6D74 C024 mov @2(stack),r0 ; address 42 6D76 0002 43 6D78 A014 a *stack,r0 ; move to end of string+1 44 6D7A 0600 dec r0 ; correct to point to last character 45 6D7C 9810 trail2 cb *r0,@_space ; compare to a space 45 6D7E 6C90 46 6D80 1301 jeq trail1 ; if a space, reduce length 47 6D82 10EC trlout jmp rndx ; else exit 48 6D84 0614 trail1 dec *stack ; reduce length 49 6D86 13EA jeq rndx ; if we get to 0 then exit 50 6D88 0600 dec r0 ; else check next address 51 6D8A 10F8 jmp trail2 52 ;] 53 54 ;[ S" Compile time:( -- ) Immediate:( -- address length ) 55 ; When Compiling: 56 ; compiles: (S") 57 ; e.g S" HELLO" compiles (S") 5 H E L L O 58 ; At the end of string compilation, HERE is aligned to an even address. 59 ; At run time, (S") (see below) pushes the address of the beginning of 60 ; the string and the length to the stack. 61 ; 62 ; When Interpreting: 63 ; Compiles the string to the address PAD, as above, and pushes the address and 64 ; length to the stack. 65 6D8C C020 _strin mov @_state,r0 ; check state 65 6D8E A048 66 6D90 160B jne _stri1 ; jump if compiling 67 68 ; not compiling, move string to PAD and adjust address 69 6D92 C034 mov *stack+,r0 ; get pad address 70 6D94 C180 mov r0,r6 ; copy it 71 6D96 C094 mov *stack,r2 ; get length 72 6D98 C064 mov @2(stack),r1 ; get source address 72 6D9A 0002 73 74 6D9C DC31 strc1 movb *r1+,*r0+ ; copy to pad 75 6D9E 0602 dec r2 76 6DA0 16FD jne strc1 77 6DA2 C906 mov r6,@2(stack) ; put PAD address in place of original 77 6DA4 0002 78 ; address 79 6DA6 10DA jmp rndx 80 81 ; compiling. compile (S") 82 6DA8 C034 _stri1 mov *stack+,r0 ; discard pad address on stack 83 6DAA C020 mov @here,r0 ; compilation address 83 6DAC A046 84 6DAE 0201 li r1,str ; CFA of (S") 84 6DB0 791E 85 6DB2 CC01 mov r1,*r0+ ' compile (S") 86 6DB4 C0B4 mov *stack+,r2 ; get length 87 6DB6 06C2 swpb r2 ; move to high byte 88 6DB8 DC02 movb r2,*r0+ ; compile length byte 89 90 6DBA 06C2 swpb r2 ; restore length 91 6DBC C074 mov *stack+,r1 ; address of string in cpu memory 92 6DBE DC31 _stri2 movb *r1+,*r0+ ; copy string to definition 93 6DC0 0602 dec r2 ; finished? 94 6DC2 16FD jne _stri2 95 6DC4 0580 inc r0 ; round up HERE 96 6DC6 0240 andi r0,>fffe ; mask off LSB 96 6DC8 FFFE 97 6DCA C800 mov r0,@here ; store it 97 6DCC A046 98 6DCE 0460 b @mpadj ; adjust memory pointers and exit via mpadj 98 6DD0 6CDA 99 ;] 100 101 ;[ (S") ( -- cpu_addr len ) 102 ; pushes the address and length of the string (compiled by S") onto the stack 103 ; On entry, PC is actually pointing at the length byte. The address of the 104 ; string is actually the address of the length byte+1. The length is just the 105 ; value of the length byte. PC is adjusted to resume execution at the first even 106 ; cell following the string. 107 6DD2 D033 _str movb *pc+,r0 ; get length 108 6DD4 0644 dect stack ; make space on stack 109 6DD6 C503 mov pc,*stack ; move address of string to stack 110 6DD8 0644 dect stack ; make space on stack 111 6DDA 0980 srl r0,8 ; place length in low byte 112 6DDC C500 mov r0,*stack ; place length on stack 113 6DDE A0C0 a r0,pc ; advance program counter 114 6DE0 0223 ai pc,1 ; round up PC... 114 6DE2 0001 115 6DE4 0243 andi pc,>fffe ; ...to an even value 115 6DE6 FFFE 116 6DE8 0460 b @retB0 116 6DEA 833A 117 ;] 118 119 ;[ NUMBER TO STRING ( num -- addr len ) 120 ; Takes a number off the stack and converts it to a signed string equivalent, 121 ; with respect to the current number base. Number base may be between 122 ; 2 and 36. The routine checks location DOSIGN, and if 0, the 123 ; number is treated as signed, else its unsigned. The routine also checks 124 ; location LZI, and, if zero, leading zero's will be supressed. 125 ; This is quite a bitch of a routine. Since any number base (between 2 and 36) 126 ; can be employed this routine is rather complex. The routine must first 127 ; determine the appropriate powers of the number base so we can divide the 128 ; target number later. Obviously this is expensive, so the routine remembers 129 ; what the active number base was the last time it was called, and ONLY 130 ; re-computes the exponents if the base has changed since the last time it was 131 ; called. 132 ; This first part computes the column values. 133 ; So, if the base is 10, you end up with 1,10,100,1000,10000 134 6DEC C385 _nts mov rstack,r14 ; save rstack 'cos we're using it 135 6DEE C254 mov *stack,r9 ; get number off stack 136 6DF0 0207 li r7,2 ; exponent counter (base^0 and base^1 are 136 6DF2 0002 137 ; easy to compute ;-) 138 ; used as a word offset into workbuffer so 139 ; counts in multiples of 2. 140 6DF4 8820 c @base,@lbase ; check if base has chaged since the last 140 6DF6 A05C 140 6DF8 A05E 141 ; time we were called 142 6DFA 1314 jeq dodiv ; base hasn't changed, no need to compute 143 ; powers of the base. 144 6DFC C820 mov @base,@lbase ; base has changed, store it in 'last base' 144 6DFE A05C 144 6E00 A05E 145 6E02 0200 li r0,1 ; base^0 is always 1 - easy ;-) 145 6E04 0001 146 6E06 0201 li r1,wrkbuf ; place to store the powers of our base 146 6E08 A222 147 ; determine base^x until result > 65535 148 6E0A CC40 mov r0,*r1+ ; store base^0 and move forward in buffer 149 6E0C C460 mov @base,*r1 ; base^1 is always base ;-) store it 149 6E0E A05C 150 6E10 C171 pwr mov *r1+,r5 ; get previous exponent 151 6E12 3960 mpy @base,r5 ; multiply it by base - lower 16 bit result 151 6E14 A05C 152 ; in r6 153 6E16 C145 mov r5,r5 ; see if the result overflowed into upper 154 ; 16 bits 155 6E18 1603 jne pwrout ; there was an overflow, exit loop 156 6E1A C446 mov r6,*r1 ; otherwise store result 157 6E1C 05C7 inct r7 ; and increment exponent counter 158 6E1E 10F8 jmp pwr ; and repeat 159 ; Ok we have computed the 'column values' (powers) for our base. Now we 160 ; sucessively divide the number down until nothing is left, building 161 ; the string equivalent as we compute each digit. Just to make life 162 ; harder for ourselves, we will optionally allow leading zero's to be 163 ; supressed. If the word at LZI<>0 then leading zero's are suppressed. 164 6E20 C807 pwrout mov r7,@expcnt ; save exponent count for next time routine 164 6E22 A060 165 ; is run 166 6E24 C1E0 dodiv mov @expcnt,r7 ; entry point when exponents arent computed. 166 6E26 A060 167 ; restore exponent count 168 6E28 0200 li r0,strbuf ; address of string buffer where we build 168 6E2A A242 169 ; the string 170 6E2C 04C1 clr r1 ; buffer length counter 171 6E2E C220 mov @dosign,r8 ; check if producing an unsigned number 171 6E30 A064 172 6E32 1609 jne ninn ; skip if we are 173 6E34 C209 mov r9,r8 ; else, check if number is negative and if 174 ; so, add "-" character 175 6E36 0248 andi r8,>8000 ; is it negative 175 6E38 8000 176 6E3A 1305 jeq ninn ; its not negative, jump 177 6E3C 0208 li r8,'-'*256 ; the number is negative, add a minus sign 177 6E3E 2D00 178 ; to the string buffer 179 6E40 DC08 movb r8,*r0+ ; place it in the buffer 180 6E42 0581 inc r1 ; increment length counter 181 6E44 0509 neg r9 ; change the number to positive 182 6E46 04C8 ninn clr r8 ; div instruction uses 32 bit dividend, our 183 ; 16 bit argument is in r9 184 6E48 C2A0 mov @lzi,r10 ; leading zero indicator 0=suppress 184 6E4A A062 185 6E4C 3E27 nxtdig div @wrkbuf(r7),r8 ; divide our number by exponent value. 185 6E4E A222 186 ; result=r8, remainder=r9 187 6E50 C208 mov r8,r8 ; was the result 0? 188 6E52 1312 jeq testlz ; if yes then check if ignoring leading 189 ; zeros 190 6E54 070A seto r10 ; not zero, so reset leading zero indicator 191 6E56 DC28 dodig movb @tlut(r8),*r0+ ; lookup digit value, move it to string 191 6E58 6E7E 192 ; buffer and advance buffer address 193 6E5A 04C8 clr r8 ; clear result for next interation 194 6E5C 0581 inc r1 ; increment length counter 195 6E5E 0647 iglz dect r7 ; done all our columns/exponents? 196 6E60 16F5 jne nxtdig ; loop if not 197 6E62 DC29 movb @tlut(r9),*r0+ ; lookup digit value, move it to string 197 6E64 6E7E 198 ; buffer and advance buffer address 199 ; we've done our division, push address & length to the stack and exit 200 6E66 0200 li r0,strbuf ; address of string buffer 200 6E68 A242 201 6E6A C500 mov r0,*stack ; move address to stack 202 6E6C 0644 dect stack ; new stack entry 203 6E6E 0581 inc r1 ; adjust length for remainder 204 6E70 C501 mov r1,*stack ; move length to stack 205 6E72 C14E mov r14,rstack ; restore return stack pointer 206 6E74 0460 b @retB0 206 6E76 833A 207 ; we're looking for leading zero's and ignoring them 208 6E78 C28A testlz mov r10,r10 ; are we ignoring leading zero's? 209 6E7A 13F1 jeq iglz ; 0=ignore leading digit 210 6E7C 10EC jmp dodig ; else do digit normally 211 ; character lookup table for printing numbers between bases 2 to 36 212 6E7E 3031 tlut text '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ' 212 6E80 3233 212 6E82 3435 212 6E84 3637 212 6E86 3839 212 6E88 4142 212 6E8A 4344 212 6E8C 4546 212 6E8E 4748 212 6E90 494A 212 6E92 4B4C 212 6E94 4D4E 212 6E96 4F50 212 6E98 5152 212 6E9A 5354 212 6E9C 5556 212 6E9E 5758 212 6EA0 595A 213 ;] * * COPY 'C:\TI\Source\TurboForth\Bank1\1-11-Editor.a99' * 1 ; ______ _ _ _ __ __ _ 2 ; | ____| | (_) | \ \ / / | | 3 ; | |__ __| |_| |_ ___ _ __ \ \ /\ / /___ _ __ __| |___ 4 ; | __| / _` | | __|/ _ \| '__| \ \/ \/ // _ \| '__/ _` / __| 5 ; | |____| (_| | | |_| (_) | | \ /\ /| (_) | | | (_| \__ \ 6 ; |______|\__,_|_|\__|\___/|_| \/ \/ \___/|_| \__,_|___/ 7 ; block editor 8 9 0000 FF83 keyCC equ -125 ; key code for ctrl c (copy line) 10 0000 FF96 keyCV equ -106 ; key code for ctrl v (paste line) 11 0000 FF89 keyCI equ -119 ; key code for ctrl i (insert line) 12 0000 FF84 keyCD equ -124 ; key code for ctrl d (delete line) 13 0000 FF8F keyCO equ -113 ; key code for ctrl o (previous block) 14 0000 FF90 keyCP equ -112 ; key code for ctrl p (next block) 15 0000 000F keyF9 equ 15 ; key code for function 9 (back) 16 17 0000 0001 keyF7 equ 1 ; key code for function 7 (tab) 18 0000 0002 keyF4 equ 2 ; key code for function 4 (escape) 19 0000 0007 keyF3 equ 7 ; key code for function 3 (erase line) 20 0000 0004 keyF2 equ 4 ; key code for function 2 (insert/overwrite) 21 0000 0003 keyF1 equ 3 ; key code for function 1 (del) 22 0000 000B keyFE equ 11 ; cursor up keycode 23 0000 0008 keyFS equ 8 ; cursor left keycode 24 0000 0009 keyFD equ 9 ; cursor right keycode 25 0000 000A keyFX equ 10 ; cursor down keycode 26 0000 0005 keyFeq equ 5 ; keycode for function = (quit) 27 0000 000D keyRET equ 13 ; keycode for ENTER key 28 29 0000 A028 savkey equ scrx ; borrow scrX memory location for saving 30 ; keypresses 31 32 6EA2 04E0 _edit clr @csrflg ; clear shared cursor flash flag 32 6EA4 A080 33 ; (shared with forcnt) 34 6EA6 04E0 clr @temp2 ; next block to load 34 6EA8 A072 35 6EAA C014 mov *stack,r0 ; get address from BLOCK 36 6EAC C080 mov r0,r2 ; copy it 37 6EAE 1603 jne _edit1 ; if not zero then continue 38 39 6EB0 05C4 inct stack ; else BLOCK failed to load block. 40 6EB2 0460 b @retB0 ; Remove vdp address from stack and exit 40 6EB4 833A 41 42 ; determine if block is dirty or clean: 43 ; display * next to block number if dirty otherwise display a space 44 6EB6 1503 _edit1 jgt _edit2 ; jump if dirty bit not set 45 6EB8 0201 li r1,'*'*256 ; block is dirty: load asterisk character 45 6EBA 2A00 46 6EBC 1002 jmp _edit3 47 6EBE 0201 _edit2 li r1,>2000 ; block is clean: load space character 47 6EC0 2000 48 ; display character next to block number 49 6EC2 0200 _edit3 li r0,10 ; load screen address 49 6EC4 000A 50 6EC6 06A0 bl @_vsbw0 ; write it to screen 50 6EC8 782C 51 52 6ECA 0242 andi r2,>7fff ; remove dirty bit if set 52 6ECC 7FFF 53 6ECE C502 mov r2,*stack ; write it back, we'll use it further on... 54 6ED0 06A0 bl @csrdef ; define cursor udg 54 6ED2 75F2 55 6ED4 04E0 clr @epage ; set page to first page 55 6ED6 A07A 56 6ED8 04E0 clr @temp ; initialise insert/overwrite mode 56 6EDA A070 57 6EDC 06A0 bl @disblk ; display block number 57 6EDE 763A 58 6EE0 06A0 bl @draws ; draw static parts of the display 58 6EE2 7408 59 6EE4 06A0 bl @drawd ; draw dynamic parts of the display 59 6EE6 73B6 60 6EE8 06A0 bl @insovr ; display mode 60 6EEA 7340 61 6EEC 04E0 clr @csrx ; used for cursor x 61 6EEE A07C 62 6EF0 04E0 clr @csry ; used for cursor y 62 6EF2 A07E 63 6EF4 04E0 clr @cursrd ; reset cursor delay 63 6EF6 A024 64 65 6EF8 06A0 bl @delay ; small delay to give the user time to 65 6EFA 75EA 66 6EFC 7530 data 30000 ; release the enter key! 67 68 ; editor main loop 69 ;[ keyboard scanning and auto-repeat 70 6EFE 06A0 edml2 bl @scnkey ; get key in r7 70 6F00 75BE 71 6F02 C807 edml4 mov r7,@savkey ; save the keypress 71 6F04 A028 72 6F06 0287 ci r7,>ffff ; nothing pressed? 72 6F08 FFFF 73 6F0A 1313 jeq docfl ; if nothing pressed then do cursor flash 74 6F0C 020D li r13,edml3 ; set something pressed - set return point 74 6F0E 6F12 75 ; for post keypress processing 76 6F10 101E jmp chkent ; process the key press 77 6F12 0200 edml3 li r0,475 ; set long delay 77 6F14 01DB 78 6F16 06A0 edml5 bl @scnkey ; scan again 78 6F18 75BE 79 6F1A 8807 c r7,@savkey ; same key as last time? 79 6F1C A028 80 6F1E 1301 jeq edml6 ; if yes then decrement delay 81 6F20 10F0 jmp edml4 ; different key - go process it 82 6F22 0600 edml6 dec r0 ; decrement counter 83 6F24 16F8 jne edml5 ; check again 84 6F26 020D li r13,edml7 ; counter expired. set return point 84 6F28 6F2C 85 6F2A 1011 jmp chkent ; go process key 86 6F2C 0200 edml7 li r0,30 ; shorter (auto-repeat) delay 86 6F2E 001E 87 6F30 10F2 jmp edml5 ; repeat 88 ;] 89 90 91 ;[ do cursorflash 92 6F32 0200 docfl li r0,>0100 92 6F34 0100 93 6F36 A800 a r0,@cursrd 93 6F38 A024 94 6F3A 16E1 jne edml2 ; time to flash cursor? loop if not 95 6F3C 0560 inv @csrflg ; invert the cursor flag 95 6F3E A080 96 6F40 1303 jeq oncsr ; if 0 do cursor on 97 6F42 06A0 bl @csroff ; else do cursor off 97 6F44 737A 98 6F46 10DB jmp edml2 99 6F48 06A0 oncsr bl @csron 99 6F4A 7374 100 6F4C 10D8 jmp edml2 101 ;] 102 103 ;[ check for enter key 104 6F4E 0287 chkent ci r7,keyRET ; return/enter pressed? 104 6F50 000D 105 6F52 1610 jne keycor ; skip if not 106 6F54 04E0 clr @csrx ; move to left most column 106 6F56 A07C 107 6F58 04E0 clr @epage ; move to left page 107 6F5A A07A 108 6F5C 05A0 inc @csry ; move down a line 108 6F5E A07E 109 6F60 C020 mov @csry,r0 ; check y 109 6F62 A07E 110 6F64 0280 ci r0,16 ; 16? 110 6F66 0010 111 6F68 1602 jne keyen1 ; skip if not 112 6F6A 04E0 clr @csry ; clip to 15 112 6F6C A07E 113 6F6E 06A0 keyen1 bl @drawd ; render display 113 6F70 73B6 114 6F72 045D b *r13 ; continue 115 ;] 116 117 ; check control keys 118 ;[ ; check CTRL O (previous block) 119 6F74 0287 keycor ci r7,keyCO 119 6F76 FF8F 120 6F78 160A jne keycpr 121 6F7A C820 mov @lstblk,@temp2 121 6F7C A1B4 121 6F7E A072 122 6F80 0620 dec @temp2 ; decrement block number to load 122 6F82 A072 123 6F84 05C4 rt4th inct stack ; remove BLOCK address from stack 124 6F86 020C li r12,_next ; restore pointer to NEXT 124 6F88 8326 125 6F8A 0460 b @retB0 ; return to forth 125 6F8C 833A 126 ;] 127 128 ;[ ; check CTRL P (next block) 129 6F8E 0287 keycpr ci r7,keyCP 129 6F90 FF90 130 6F92 1606 jne keycdr 131 6F94 C820 mov @lstblk,@temp2 131 6F96 A1B4 131 6F98 A072 132 6F9A 05A0 inc @temp2 ; increment block number to load 132 6F9C A072 133 6F9E 10F2 jmp rt4th ; return to forth 134 ;] 135 136 ;[ ; check CTRL D (delete line) 137 6FA0 0287 keycdr ci r7,keyCD ; ctrl d pressed? 137 6FA2 FF84 138 6FA4 1628 jne keycir ; skip if not 139 6FA6 06A0 bl @needud ; set this blocks' status to dirty 139 6FA8 7616 140 ; calculate end address of buffer 141 6FAA C194 mov *stack,r6 ; vdp buffer address 142 6FAC 0226 ai r6,1023 ; point to last byte of buffer 142 6FAE 03FF 143 ; calculate start point 144 6FB0 C020 mov @csry,r0 ; get current line 144 6FB2 A07E 145 6FB4 0580 inc r0 ; move down a line 146 6FB6 0A60 sla r0,6 ; multiply by buffer line length 147 6FB8 A014 a *stack,r0 ; add vdp buffer start address 148 6FBA 0202 keycd1 li r2,64 ; read a line... 148 6FBC 0040 149 6FBE C060 mov @here,r1 ; ...into scroll buffer 149 6FC0 A046 150 6FC2 06A0 bl @_vmbr ; read the line 150 6FC4 7806 151 6FC6 0220 ai r0,-64 ; move up one line 151 6FC8 FFC0 152 6FCA C060 mov @here,r1 ; source 152 6FCC A046 153 6FCE 0202 li r2,64 ; count 153 6FD0 0040 154 6FD2 06A0 bl @_vmbw0 ; write the line 154 6FD4 7854 155 6FD6 0220 ai r0,128 ; move down 2 lines 155 6FD8 0080 156 6FDA 8180 c r0,r6 ; done all? 157 6FDC 11EE jlt keycd1 ; loop if not 158 ; blank the last line... r6 points to last byte, so... 159 6FDE C006 mov r6,r0 ; place in r0 for VDP 160 6FE0 0220 ai r0,-63 ; move to start of last line in buffer 160 6FE2 FFC1 161 6FE4 0201 li r1,>2000 ; space character 161 6FE6 2000 162 6FE8 0202 li r2,64 ; line length 162 6FEA 0040 163 6FEC 06A0 bl @vsbwmi ; write spaces 163 6FEE 7880 164 6FF0 06A0 bl @rsrc ; render source 164 6FF2 74DC 165 6FF4 045D b *r13 ; continue 166 ;] 167 168 ;[ ; check CTRL I (insert line) 169 6FF6 0287 keycir ci r7,keyCI ; ctrl i pressed? 169 6FF8 FF89 170 6FFA 1628 jne keyccr ; skip if not 171 6FFC 06A0 bl @needud ; set this blocks' status to dirty 171 6FFE 7616 172 ; get current line address 173 7000 C1A0 mov @csry,r6 ; current y 173 7002 A07E 174 7004 0286 ci r6,15 ; on the last line? 174 7006 000F 175 7008 1317 jeq keyci2 ; if so, just erase last line 176 700A 0A66 sla r6,6 ; multiply by line length 177 700C A194 a *stack,r6 ; add vdp buffer address 178 ; find last line of buffer 179 700E C014 mov *stack,r0 ; buffer start address 180 7010 0220 ai r0,14*64 ; move to last line but 1 (15th line) 180 7012 0380 181 7014 C060 keyci1 mov @here,r1 ; buffer address 181 7016 A046 182 7018 0202 li r2,64 ; count 182 701A 0040 183 701C 06A0 bl @_vmbr ; read into buffer 183 701E 7806 184 7020 0220 ai r0,64 ; move down a line 184 7022 0040 185 7024 C060 mov @here,r1 ; buffer address 185 7026 A046 186 7028 0202 li r2,64 ; count 186 702A 0040 187 702C 06A0 bl @_vmbw0 ; write the line 187 702E 7854 188 7030 0220 ai r0,-128 ; move up 2 lines 188 7032 FF80 189 7034 8180 c r0,r6 ; finished? 190 7036 14EE jhe keyci1 ; repeat if not 191 ; erase current line, address is in r6 192 7038 C006 keyci2 mov r6,r0 ; for vdp 193 703A 0201 li r1,>2000 ; space 193 703C 2000 194 703E 0202 li r2,64 ; count 194 7040 0040 195 7042 06A0 bl @vsbwmi ; write 64 spaces 195 7044 7880 196 7046 06A0 bl @rsrc ; render source window 196 7048 74DC 197 704A 045D b *r13 ; continue 198 ;] 199 200 ;[ ; check CTRL C (copy) 201 704C 0287 keyccr ci r7,keyCC ; ctrl C pressed? 201 704E FF83 202 7050 160E jne keyCVr ; skip if not 203 7052 0200 li r0,64 ; buffer pitch 203 7054 0040 204 7056 C060 mov @csry,r1 ; get cursor y 204 7058 A07E 205 705A 3840 mpy r0,r1 ; multiply them (result in r2) 206 705C A094 a *stack,r2 ; add vdp buffer address 207 705E C002 mov r2,r0 ; move to r0 for vdp actions 208 7060 0201 li r1,tib ; destination 208 7062 3420 209 7064 0202 li r2,64 ; number of bytes to read 209 7066 0040 210 7068 06A0 bl @_vmbr ; read them into scroll buffer 210 706A 7806 211 706C 045D b *r13 ; continue 212 ;] 213 214 ;[ ; check CTRL V (paste) 215 706E 0287 keyCVr ci r7,keyCV ; ctrl V pressed? 215 7070 FF96 216 7072 1615 jne keyf1r ; skip if not 217 7074 C020 mov @tib,r0 ; check buffer contents 217 7076 3420 218 7078 1311 jeq nopast ; if 0, nothing to paste 219 707A 0200 li r0,64 ; buffer pitch 219 707C 0040 220 707E C060 mov @csry,r1 ; get cursor y 220 7080 A07E 221 7082 3840 mpy r0,r1 ; multiply them (result in r2) 222 7084 A094 a *stack,r2 ; add vdp buffer address 223 7086 C002 mov r2,r0 ; move to r0 for vdp actions 224 7088 0201 li r1,tib ; source 224 708A 3420 225 708C 0202 li r2,64 ; number of bytes to write 225 708E 0040 226 7090 06A0 bl @_vmbw0 ; write them into source buffer 226 7092 7854 227 7094 06A0 bl @rsrc ; render window 227 7096 74DC 228 7098 06A0 bl @needud ; mark block for update 228 709A 7616 229 709C 045D nopast b *r13 ; continue 230 ;] 231 232 ; check function keys 233 ;[ ; check f1 (del) 234 709E 0287 keyf1r ci r7,keyF1 ; f1 pressed? 234 70A0 0003 235 70A2 162F jne keyf9r ; skip if not 236 70A4 06A0 bl @needud ; set this blocks' status to dirty 236 70A6 7616 237 ; calculate endpoint 238 70A8 C060 mov @csry,r1 ; get y 238 70AA A07E 239 70AC 0581 inc r1 ; move down one line 240 70AE 0A61 sla r1,6 ; multiply by buffer line length (64) 241 70B0 0601 dec r1 ; point to last char on current line 242 70B2 A054 a *stack,r1 ; add in vdp buffer address 243 70B4 C181 mov r1,r6 ; save it 244 ; calculate start point 245 70B6 C0A0 mov @csry,r2 ; get y 245 70B8 A07E 246 70BA 0A62 sla r2,6 ; multiply by buffer line length (64) 247 70BC A0A0 a @csrx,r2 ; add x 247 70BE A07C 248 70C0 A094 a *stack,r2 ; add in vdp address 249 70C2 C020 mov @epage,r0 ; check page 249 70C4 A07A 250 70C6 1302 jeq keyf1s ; skip if 0 251 70C8 0222 ai r2,30 ; account for page offset 251 70CA 001E 252 70CC C002 keyf1s mov r2,r0 ; set start point for vdp read 253 70CE 6042 s r2,r1 ; calculate length 254 70D0 C081 mov r1,r2 ; put in r2 for vmbr 255 70D2 0582 inc r2 256 70D4 C200 mov r0,r8 ; save buffer address 257 70D6 C242 mov r2,r9 ; save length 258 ; read from source buffer 259 70D8 C060 mov @here,r1 ; cpu buffer 259 70DA A046 260 70DC 06A0 bl @_vmbr ; read into buffer 260 70DE 7806 261 70E0 C008 mov r8,r0 ; restore addresds 262 70E2 C089 mov r9,r2 ; restore count 263 70E4 0602 dec r2 ; reduce by 1 264 70E6 1305 jeq f1eol ; if on last column then skip 265 70E8 C060 mov @here,r1 ; move forward... 265 70EA A046 266 70EC 0581 inc r1 ; ...1 char in the buffer 267 70EE 06A0 bl @_vmbw0 ; write it 267 70F0 7854 268 70F2 C006 f1eol mov r6,r0 ; end of line address 269 70F4 0201 li r1,>2000 ; write a space character to end of line 269 70F6 2000 270 70F8 06A0 bl @_vsbw0 270 70FA 782C 271 70FC 06A0 bl @rsrc ; render source to window 271 70FE 74DC 272 7100 045D b *r13 ; continue 273 ;] 274 275 ;[ ; check f9 (back) 276 7102 0287 keyf9r ci r7,keyF9 276 7104 000F 277 7106 1604 jne keyf3r 278 7108 04E0 clr @tib ; clr length byte in TIB to stop Forth from 278 710A 3420 279 ; trying to process the copy/paste buffer as 280 ; input! 281 710C 0460 ret4th b @rt4th ; return to forth 281 710E 6F84 282 ;] 283 284 ;[ ; check f3 (erase line) 285 7110 0287 keyf3r ci r7,keyF3 285 7112 0007 286 7114 1616 jne keyf7r 287 7116 0200 li r0,64 ; buffer pitch 287 7118 0040 288 711A C060 mov @csry,r1 ; get cursor y 288 711C A07E 289 711E 3840 mpy r0,r1 ; multiply them (result in r2) 290 7120 A094 a *stack,r2 ; add vdp buffer address 291 7122 C002 mov r2,r0 ; move to r0 for vdp actions 292 7124 0201 li r1,>2000 ; space character 292 7126 2000 293 7128 0202 li r2,64 ; 64 bytes to erase 293 712A 0040 294 712C 06A0 bl @vsbwmi ; erase them 294 712E 7880 295 7130 04E0 clr @csrx ; move to leftmost column 295 7132 A07C 296 7134 04E0 clr @epage ; left page 296 7136 A07A 297 7138 06A0 bl @rsrc ; render source in window 297 713A 74DC 298 713C 06A0 bl @needud ; set block for update 298 713E 7616 299 7140 045D b *r13 ; continue 300 ;] 301 302 ;[ ; check f7 key 303 7142 0287 keyf7r ci r7,keyF7 ; F7 pressed? 303 7144 0001 304 7146 160A jne keyfqr ; skip if not 305 7148 06A0 bl @is80c ; 80 column mode? 305 714A 767A 306 714C 1306 jeq f7exit ; dump the keypress if yes - f7 key not used 307 ; in 80 column mode 308 714E 06A0 bl @csroff ; restore character under cursor 308 7150 737A 309 7152 0560 inv @epage ; switch page 309 7154 A07A 310 7156 06A0 bl @drawd ; re-draw screen 310 7158 73B6 311 715A 045D f7exit b *r13 312 ;] 313 314 ;[ ; check quit key 315 715C 0287 keyfqr ci r7,keyFeq ; quit pressed? 315 715E 0005 316 7160 160F jne keyf2r ; skip if not 317 7162 C020 edF4 mov @lstblk,r0 ; get current block 317 7164 A1B4 318 7166 06A0 bl @scnblk ; locate it (blk address in r0) 318 7168 69A0 319 716A 04D1 clr *r1 ; un-assign this buffer 320 716C 05C1 inct r1 ; point to VDP address pointer 321 716E C011 mov *r1,r0 ; get the VDP address 322 7170 0240 andi r0,>7fff ; reset dirty bit 322 7172 7FFF 323 7174 C440 mov r0,*r1 ; write it back 324 7176 04E0 clr @tib ; clr length byte in TIB to stop Forth from 324 7178 3420 325 ; trying to process the copy/paste buffer as 326 ; input! 327 717A 06A0 bl @cls_ ; clear screen 327 717C 613A 328 717E 10C6 jmp ret4th ; return to Forth 329 ;] 330 331 ;[ ; check f2 key 332 7180 0287 keyf2r ci r7,keyF2 ; F2 pressed? 332 7182 0004 333 7184 1603 jne keyd ; skip if not 334 7186 06A0 bl @insovr 334 7188 7340 335 718A 045D b *r13 336 ;] 337 338 ;[ ; check for fctn + d 339 718C 0287 keyd ci r7,keyFD ; fctn & d? 339 718E 0009 340 7190 1621 jne keys ; skip if not 341 7192 06A0 bl @csroff ; restore character currently under cursor 341 7194 737A 342 7196 06A0 bl @is80c 342 7198 767A 343 719A 1605 jne keyd1 344 719C C020 mov @csrx,r0 344 719E A07C 345 71A0 0280 ci r0,63 345 71A2 003F 346 71A4 1004 jmp keyd2 347 71A6 C020 keyd1 mov @csrx,r0 ; get cursor x 347 71A8 A07C 348 71AA 0280 ci r0,33 ; check limit 348 71AC 0021 349 71AE 1306 keyd2 jeq clipxh ; clip if on limit 350 71B0 0580 inc r0 ; otherwise increment 351 71B2 C800 mov r0,@csrx ; write it back 351 71B4 A07C 352 71B6 06A0 bl @csron ; set cursor to on state 352 71B8 7374 353 71BA 045D b *r13 354 71BC 04E0 clipxh clr @csrx ; clip cursor 354 71BE A07C 355 71C0 06A0 clipxg bl @is80c ; 80 column? 355 71C2 767A 356 71C4 1306 jeq keydx 357 71C6 0560 inv @epage ; change page 357 71C8 A07A 358 71CA 06A0 bl @drawd ; draw window contents 358 71CC 73B6 359 71CE 06A0 bl @csron ; set cursor to on state 359 71D0 7374 360 71D2 045D keydx b *r13 361 ;] 362 363 ;[ ; check for fctn + s 364 71D4 0287 keys ci r7,keyFS ; fctn & s 364 71D6 0008 365 71D8 1618 jne keye ; skip if not 366 71DA 06A0 bl @csroff ; restore character currently under cursor 366 71DC 737A 367 71DE C020 mov @csrx,r0 ; get cursor x 367 71E0 A07C 368 71E2 1306 jeq clipxl ; clip if on limit 369 71E4 0600 dec r0 ; otherwise decrement 370 71E6 C800 mov r0,@csrx ; write it back 370 71E8 A07C 371 71EA 06A0 bl @csron ; set cursor on 371 71EC 7374 372 71EE 045D b *r13 373 71F0 06A0 clipxl bl @is80c ; 80 column? 373 71F2 767A 374 71F4 1305 jeq clipx2 375 71F6 0200 li r0,33 ; set cursor to the other end 375 71F8 0021 376 71FA C800 mov r0,@csrx ; write it 376 71FC A07C 377 71FE 10E0 jmp clipxg ; change page and render 378 7200 0200 clipx2 li r0,63 ; set cursor to other end (80 col mode) 378 7202 003F 379 7204 C800 mov r0,@csrx 379 7206 A07C 380 7208 045D b *r13 381 ;] 382 383 ;[ ; check for fctn + e 384 720A 0287 keye ci r7,keyFE ; fctn & e 384 720C 000B 385 720E 1610 jne keyx ; skip if not 386 7210 06A0 bl @csroff ; restore character currently under cursor 386 7212 737A 387 7214 C020 mov @csry,r0 ; get cursor y 387 7216 A07E 388 7218 0600 dec r0 ; decrement 389 721A C800 mov r0,@csry ; write it back 389 721C A07E 390 721E 1103 jlt clipyl ; clip if on limit 391 7220 06A0 clipyg bl @csron ; set cursor on 391 7222 7374 392 7224 045D b *r13 393 7226 0200 clipyl li r0,15 ; set cursor to the other end 393 7228 000F 394 722A C800 mov r0,@csry ; write it 394 722C A07E 395 722E 10F8 jmp clipyg 396 ;] 397 398 ;[ ; check for fctn + x 399 7230 0287 keyx ci r7,keyFX ; fctn & x? 399 7232 000A 400 7234 160F jne genkey ; skip if not 401 7236 06A0 bl @csroff ; restore character currently under cursor 401 7238 737A 402 723A C020 mov @csry,r0 ; get cursor y 402 723C A07E 403 723E 0580 inc r0 ; increment it 404 7240 C800 mov r0,@csry ; write it back 404 7242 A07E 405 7244 0280 ci r0,16 ; compare to limit 405 7246 0010 406 7248 1301 jeq clipyh ; clip if on limit 407 724A 10EA jmp clipyg 408 724C 04C0 clipyh clr r0 ; set cursor to the other end 409 724E C800 mov r0,@csry ; write it 409 7250 A07E 410 7252 10E6 jmp clipyg 411 ;] 412 413 ;[ process general keypress 414 7254 06A0 genkey bl @needud ; mark the block for update 414 7256 7616 415 7258 06A0 bl @doins ; do insert if insert mode is selected 415 725A 72EA 416 725C 0200 li r0,64 ; buffer pitch 416 725E 0040 417 7260 C060 mov @csry,r1 ; current y 417 7262 A07E 418 7264 3840 mpy r0,r1 ; calculate buffer address 419 7266 A0A0 a @csrx,r2 ; add x 419 7268 A07C 420 726A C020 mov @epage,r0 ; check page 420 726C A07A 421 726E 1302 jeq gkno ; skip if on page 0 422 7270 0222 ai r2,30 ; else account for page offset 422 7272 001E 423 7274 C002 gkno mov r2,r0 ; move to r0 for vdp address 424 7276 A014 a *stack,r0 ; add vdp buffer address 425 7278 C047 mov r7,r1 ; get keypress 426 727A 06C1 swpb r1 ; move to high byte 427 727C 06A0 bl @_vsbw0 ; write it into vdp 427 727E 782C 428 7280 06A0 bl @csroff ; display it 428 7282 737A 429 7284 C020 mov @csrx,r0 ; get x 429 7286 A07C 430 7288 0580 inc r0 ; move to the right 431 728A C800 mov r0,@csrx ; store it 431 728C A07C 432 728E C060 mov @xmax,r1 ; get xmax 432 7290 A02C 433 7292 0281 ci r1,80 ; 80 column 433 7294 0050 434 7296 1304 jeq chk80 ; jump if in 80 column mode 435 7298 0280 ci r0,34 ; need to clip? (40 column mode check) 435 729A 0022 436 729C 1625 jne upkey ; jump if not 437 729E 100D jmp gkeycx ; else do clip 438 72A0 0280 chk80 ci r0,64 ; limit for 80 column mode 438 72A2 0040 439 72A4 1621 jne upkey ; jump if clip not required 440 72A6 04E0 clr @csrx ; zero x 440 72A8 A07C 441 72AA C020 mov @csry,r0 ; get y 441 72AC A07E 442 72AE 0580 inc r0 ; add 1 443 72B0 0240 andi r0,15 ; clip to 16th line 443 72B2 000F 444 72B4 C800 mov r0,@csry ; store y again 444 72B6 A07E 445 72B8 1017 jmp upkey ; and continue 446 ; clip x and change page 447 72BA 04E0 gkeycx clr @csrx ; zero x 447 72BC A07C 448 72BE 0560 inv @epage ; change page 448 72C0 A07A 449 72C2 1304 jeq ncos ; no cursor offset required if page=0 450 72C4 0200 li r0,4 ; cursor position 450 72C6 0004 451 72C8 C800 mov r0,@csrx ; set it 451 72CA A07C 452 72CC C020 ncos mov @epage,r0 ; get page 452 72CE A07A 453 72D0 1609 jne ncos1 ; skip if page=1 454 72D2 05A0 incyc inc @csry ; move down to next line 454 72D4 A07E 455 72D6 C020 mov @csry,r0 ; check y 455 72D8 A07E 456 72DA 0280 ci r0,16 ; need to clip y 456 72DC 0010 457 72DE 1602 jne ncos1 ; skip if no need 458 72E0 0620 dec @csry ; else reset to 15th line 458 72E2 A07E 459 72E4 06A0 ncos1 bl @drawd ; draw window and rulers etc 459 72E6 73B6 460 72E8 045D upkey b *r13 461 ;] 462 463 464 ;[ insert mode 465 ; move everything *on the current line only* forward, from the cursor 466 72EA C28B doins mov r11,r10 467 72EC C020 mov @temp,r0 ; check insert mode 467 72EE A070 468 72F0 1626 jne doinsx ; if not 0 then exit 469 ; calculate endpoint address in vdp buffer... 470 72F2 C0A0 mov @csry,r2 ; get y 470 72F4 A07E 471 72F6 0582 inc r2 ; move to next line 472 72F8 0A62 sla r2,6 ; multiply by 64 473 72FA 0602 dec r2 ; point to last byte on current line 474 72FC A094 a *stack,r2 ; add in vdp buffer address 475 ; calculate startpoint address in vdp buffer... 476 72FE C020 mov @csry,r0 ; current line 476 7300 A07E 477 7302 0A60 sla r0,6 ; multiply by block line length (64) 478 7304 A020 a @csrx,r0 ; add x 478 7306 A07C 479 7308 C060 mov @epage,r1 ; check page 479 730A A07A 480 730C 1302 jeq doins1 ; skip if page=0 481 730E 0220 ai r0,30 ; else add offset 481 7310 001E 482 7312 A014 doins1 a *stack,r0 ; add in vdp buffer address 483 7314 6080 s r0,r2 ; calculate length 484 7316 1313 jeq doinsx ; exit if 0 485 ; read buffer contents into temporary buffer and write them out again, 486 ; forward by 1 character... 487 7318 C060 mov @here,r1 ; buffer to store the data in 487 731A A046 488 731C C240 mov r0,r9 ; save address 489 731E C202 mov r2,r8 ; save length 490 7320 06A0 bl @_vmbr ; read data into buffer 490 7322 7806 491 7324 C009 mov r9,r0 ; restore address 492 7326 0580 inc r0 ; move forward 1 493 7328 C088 mov r8,r2 ; restore length 494 732A C060 mov @here,r1 ; source for vdp write 494 732C A046 495 732E 06A0 bl @_vmbw0 ; write the characters 495 7330 7854 496 7332 C807 mov r7,@temp3 ; save keypress 496 7334 A074 497 7336 06A0 bl @rsrc ; render source window 497 7338 74DC 498 733A C1E0 mov @temp3,r7 ; restore keypress for handling by keypress 498 733C A074 499 ; routine 500 733E 045A doinsx b *r10 501 ;] 502 503 504 ;[ set insert/overwrite mode 505 7340 C1CB insovr mov r11,r7 ; save return address 506 7342 05A0 inc @temp ; advance to next mode 506 7344 A070 507 7346 8820 c @temp,@modmax ; compare to maximum allowed value 507 7348 A070 507 734A 7372 508 734C 1602 jne ins1 ; if <= to max then ok 509 734E 04E0 clr @temp ; else reset to 0 509 7350 A070 510 7352 06A0 ins1 bl @xya ; set screen address 510 7354 7580 511 7356 2200 data >2200 512 7358 C060 mov @temp,r1 ; get mode 512 735A A070 513 735C 1605 jne ovr ; set insert mode if 1 514 735E 06A0 bl @wstr ; else insert mode 0 514 7360 75B2 515 7362 76FF data instxt,6 515 7364 0006 516 7366 0457 b *r7 517 7368 06A0 ovr bl @wstr ; overwrite (1) 517 736A 75B2 518 736C 7705 data ovrtxt,6 518 736E 0006 519 7370 0457 b *r7 520 7372 0002 modmax data 2 521 ;] 522 523 524 ;[ cursor blinking routines 525 ; display cursor character 526 7374 C18B csron mov r11,r6 527 7376 04C7 clr r7 528 7378 100F jmp calcsr ; calculate cursor position and display r7 529 530 ; restore character under cursor 531 737A C18B csroff mov r11,r6 ; save return address 532 737C C020 mov @csry,r0 ; cursor y 532 737E A07E 533 7380 0A60 sla r0,6 ; multiply by block line pitch (64) 534 7382 A020 a @csrx,r0 ; add x 534 7384 A07C 535 7386 A014 a *stack,r0 ; add buffer address 536 7388 C060 mov @epage,r1 ; check page 536 738A A07A 537 738C 1302 jeq csr1 ; skip if on page 0 538 738E 0220 ai r0,30 ; else add page offset 538 7390 001E 539 7392 06A0 csr1 bl @_vsbr ; read byte from buffer 539 7394 77E4 540 7396 D1C1 movb r1,r7 ; save character 541 7398 C020 calcsr mov @csry,r0 ; cursor y 541 739A A07E 542 739C 0220 ai r0,3 ; account for editor window 542 739E 0003 543 73A0 3820 mpy @xmax,r0 ; multiply by screen pitch (result in r1) 543 73A2 A02C 544 73A4 C020 mov @csrx,r0 ; get x 544 73A6 A07C 545 73A8 0220 ai r0,3 ; account for editor window 545 73AA 0003 546 73AC A001 a r1,r0 ; sum to r0 for vdp address 547 73AE C047 mov r7,r1 ; get the character we saved 548 73B0 06A0 bl @_vsbw0 ; write it 548 73B2 782C 549 73B4 0456 b *r6 ; return to caller 550 ;] 551 552 553 ; screen handling routines 554 ;[ draw dynamic parts of the screen 555 73B6 C28B drawd mov r11,r10 ; save return address 556 ; draw left vertical line 557 73B8 06A0 bl @lftlin 557 73BA 752E 558 ; draw right vertical line 559 73BC 06A0 bl @rtlin 559 73BE 7550 560 ; draw top ruler 561 73C0 06A0 bl @is80c ; 80 column mode? 561 73C2 767A 562 73C4 1310 jeq ru80c ; jump if yes 563 73C6 06A0 bl @xya 563 73C8 7580 564 73CA 0301 data >0301 ; get screen address for x=3 y=1 565 73CC C060 mov @epage,r1 565 73CE A07A 566 73D0 1605 jne trul1 567 73D2 06A0 bl @wstr ; write string 567 73D4 75B2 568 73D6 7684 data txt0,31 ; source,length 568 73D8 001F 569 73DA 1013 jmp ednext 570 73DC 06A0 trul1 bl @wstr ; write string 570 73DE 75B2 571 73E0 76A3 data txt1,31 ; source,length 571 73E2 001F 572 73E4 100E jmp ednext 573 ; render ruler (80 column mode) 574 73E6 06A0 ru80c bl @xya 574 73E8 7580 575 73EA 0301 data >0301 ; get screen address for x=3 y=1 576 73EC 06A0 bl @wstr ; write string 576 73EE 75B2 577 73F0 7684 data txt0,30 ; source,length 577 73F2 001E 578 73F4 06A0 bl @xya 578 73F6 7580 579 73F8 2101 data >2101 ; get screen address for x=33 y=1 580 73FA 06A0 bl @wstr ; write string 580 73FC 75B2 581 73FE 76A3 data txt1,31 ; source,length 581 7400 001F 582 583 ; render block text into editor window 584 ; vdp address is on the stack 585 7402 06A0 ednext bl @rsrc ; render source into window 585 7404 74DC 586 7406 045A b *r10 ; return to caller 587 ;] 588 589 ;[ draw static parts of the screen 590 7408 C28B draws mov r11,r10 ; save return address 591 ; write block text 592 740A 06A0 bl @xya 592 740C 7580 593 740E 0000 data >0000 594 7410 06A0 bl @wstr 594 7412 75B2 595 7414 76F4 data blktxt,6 595 7416 0006 596 ; write mode text 597 7418 06A0 bl @xya 597 741A 7580 598 741C 1D00 data >1d00 599 741E 06A0 bl @wstr 599 7420 75B2 600 7422 76FA data modtxt,5 600 7424 0005 601 ; draw 2nd ruler line 602 7426 06A0 bl @xya 602 7428 7580 603 742A 0302 data >0302 ; get screen address for x=3 y=2 604 742C 06A0 bl @wstr ; write string 604 742E 75B2 605 7430 76C2 data txt2,34 ; source,length 605 7432 0022 606 7434 06A0 bl @is80c ; running 80 column? 606 7436 767A 607 7438 1607 jne lhl ; jump if not 608 743A 06A0 bl @xya 608 743C 7580 609 743E 2502 data >2502 ; x=37 y=2 610 7440 06A0 bl @wstr 610 7442 75B2 611 7444 76C6 data txt2+4,30 611 7446 001E 612 ; draw lower horizontal line 613 7448 06A0 lhl bl @is80c ; in 80 column mode? 613 744A 767A 614 744C 1608 jne lhl1 615 744E 06A0 bl @xya 615 7450 7580 616 7452 0313 data >0313 ; x=3 y=19 617 7454 06A0 bl @hline 617 7456 75A6 618 7458 0100 data 1*256,64 618 745A 0040 619 745C 1007 jmp rownum 620 745E 06A0 lhl1 bl @xya 620 7460 7580 621 7462 0313 data >0313 ; x=3 y=19 622 7464 06A0 bl @hline 622 7466 75A6 623 7468 0100 data 1*256,35 623 746A 0023 624 625 ; place row numbers 626 746C 06A0 rownum bl @xya 626 746E 7580 627 7470 0103 data >0103 ; get screen address for x=1 y=3 628 7472 0202 li r2,16 ; count 628 7474 0010 629 7476 0206 li r6,rowtxt ; source 629 7478 76E4 630 747A D076 rl1 movb *r6+,r1 ; get source character 631 747C 06A0 bl @_vsbw0 ; write a character 631 747E 782C 632 7480 0581 inc r1 ; next source character 633 7482 A020 a @xmax,r0 ; move down a line 633 7484 A02C 634 7486 0602 dec r2 ; finished? 635 7488 16F8 jne rl1 ; loop if not 636 748A 06A0 bl @xya 636 748C 7580 637 748E 000D data >000d ; x=0 y=13 638 7490 06A0 bl @vline 638 7492 7592 639 7494 3100 data '1'*256,6 639 7496 0006 640 641 ; place corner peices 642 7498 0207 li r7,4 ; count 642 749A 0004 643 749C 0206 li r6,cnrdat ; address of corner data 643 749E 74CC 644 74A0 06A0 bl @is80c ; 80 column? 644 74A2 767A 645 74A4 1602 jne corner ; jump if not 646 74A6 0226 ai r6,8 ; else point to 80 column data 646 74A8 0008 647 74AA 0201 corner li r1,4*256 ; ascii 4 in msb 647 74AC 0400 648 74AE C036 crnlp mov *r6+,r0 ; get address 649 74B0 06A0 bl @_vsbw0 ; write to screen 649 74B2 782C 650 74B4 0221 ai r1,>0100 ; increment ascii character 650 74B6 0100 651 74B8 0607 dec r7 ; decrement counter 652 74BA 16F9 jne crnlp ; loop if not finished 653 654 ; draw help text 655 74BC 06A0 bl @xya 655 74BE 7580 656 74C0 0014 data >0014 657 74C2 06A0 bl @wstr 657 74C4 75B2 658 74C6 7743 data help,4*40 658 74C8 00A0 659 74CA 045A b *r10 ; return to caller 660 661 ; location data for corner UDGs - 40 column mode 662 74CC 0052 cnrdat data 2*40+2 ; top left 663 74CE 0075 data 2*40+37 ; top right 664 74D0 02FA data 19*40+2 ; bottom left 665 74D2 031D data 19*40+37 ; bottom right 666 667 ; location data for corner UDGs - 80 column mode 668 74D4 00A2 data 2*80+2 ; top left 669 74D6 00E3 data 2*80+67 ; top right 670 74D8 05F2 data 19*80+2 ; bottom left 671 74DA 0633 data 19*80+67 ; bottom right 672 ;] 673 674 ;[ render source subroutine 675 0000 0023 pitch equ 35 676 74DC C38B rsrc mov r11,r14 ; save return address 677 74DE 020F li r15,pitch ; load pitch for 40 column mode 677 74E0 0023 678 74E2 06A0 bl @is80c 678 74E4 767A 679 74E6 1602 jne rsrc_ 680 74E8 020F li r15,65 ; load pitch for 80 column mode 680 74EA 0041 681 74EC 06A0 rsrc_ bl @xya 681 74EE 7580 682 74F0 0303 data >0303 ; screen address 683 74F2 C240 mov r0,r9 ; save it 684 74F4 C194 mov *stack,r6 ; source vdp address 685 74F6 C220 mov @epage,r8 ; check page 685 74F8 A07A 686 74FA 1302 jeq rsrc1 687 74FC 0226 ai r6,30 ; calculate page offset 687 74FE 001E 688 7500 020C rsrc1 li r12,16 ; line count 688 7502 0010 689 7504 C006 rloop mov r6,r0 ; source 690 7506 C060 mov @here,r1 ; destination 690 7508 A046 691 750A C08F mov r15,r2 ; count 692 750C 0602 dec r2 693 750E 06A0 bl @_vmbr ; read a line 693 7510 7806 694 7512 C009 mov r9,r0 ; destination address 695 7514 C060 mov @here,r1 ; source 695 7516 A046 696 7518 C08F mov r15,r2 ; count 697 751A 0602 dec r2 698 751C 06A0 bl @_vmbw0 ; write it 698 751E 7854 699 7520 A260 a @xmax,r9 ; down a line 699 7522 A02C 700 7524 0226 ai r6,64 ; next line in source 700 7526 0040 701 7528 060C dec r12 ; finished? 702 752A 16EC jne rloop ; loop if not 703 752C 045E b *r14 ; return 704 ;] 705 706 ;[ draw left hand vertical line (dependant on which page we're on) 707 752E C1CB lftlin mov r11,r7 ; save return addressd 708 7530 06A0 bl @xya 708 7532 7580 709 7534 0203 data >0203 ; get screen address for x=2 y=3 710 7536 C060 mov @epage,r1 ; get page 710 7538 A07A 711 753A 1605 jne lft1 ; do if page=1 712 753C 06A0 bl @vline 712 753E 7592 713 7540 0300 data 3*256,16 713 7542 0010 714 7544 0457 b *r7 715 7546 06A0 lft1 bl @vline 715 7548 7592 716 754A 9C00 data '<'+96*256,16 716 754C 0010 717 754E 0457 b *r7 718 ;] 719 720 ;[ draw right hand vertical line (dependant on which page we're on) 721 7550 C1CB rtlin mov r11,r7 ; save return address 722 7552 06A0 bl @is80c ; 80 column? 722 7554 767A 723 7556 1310 jeq rt2 724 7558 06A0 bl @xya 724 755A 7580 725 755C 2503 data >2503 ; get screen address for x=37 y=3 726 755E C060 mov @epage,r1 ; get page 726 7560 A07A 727 7562 1605 jne rt1 ; do if page=1 728 7564 06A0 bl @vline 728 7566 7592 729 7568 9E00 data '>'+96*256,16 729 756A 0010 730 756C 0457 b *r7 ; return 731 756E 06A0 rt1 bl @vline 731 7570 7592 732 7572 0300 data 3*256,16 732 7574 0010 733 7576 0457 b *r7 ; return 734 7578 06A0 rt2 bl @xya ; 80 column mode only: place vertical bar on 734 757A 7580 735 ; rhs of screen 736 757C 4303 data >4303 737 757E 10F7 jmp rt1 738 ;] 739 740 ;[ calculate screen address from XY coordinates 741 7580 C03B xya mov *r11+,r0 ; get xy 742 7582 C040 mov r0,r1 ; copy 743 7584 0A81 sla r1,8 ; get y (move x out) 744 7586 0881 sra r1,8 ; adjust to correct position 745 7588 0880 sra r0,8 ; get x (move y out) 746 758A 3860 mpy @xmax,r1 ; do y multiply (result in r2) 746 758C A02C 747 758E A002 a r2,r0 ; screen address in r0 748 7590 045B rt 749 ;] 750 751 ;[ draw a vertical line subroutine 752 ; r0=screen address 753 ; character and length follow as DATA directives in caller code 754 7592 C07B vline mov *r11+,r1 755 7594 C0BB mov *r11+,r2 756 7596 C18B mov r11,r6 757 7598 06A0 vline1 bl @_vsbw0 757 759A 782C 758 759C A020 a @xmax,r0 758 759E A02C 759 75A0 0602 dec r2 760 75A2 16FA jne vline1 761 75A4 0456 b *r6 762 ;] 763 764 ;[ draw a horizontal line subroutine 765 ; r0=screen address 766 ; character and length follow as DATA directives in caller code 767 75A6 C07B hline mov *r11+,r1 768 75A8 C0BB mov *r11+,r2 769 75AA C18B mov r11,r6 770 75AC 06A0 bl @vsbwmi 770 75AE 7880 771 75B0 0456 b *r6 772 ;] 773 774 ;[ write string subroutine 775 ; r0=screen address 776 ; source and length follow as DATA directives in caller code 777 75B2 C07B wstr mov *r11+,r1 ; source 778 75B4 C0BB mov *r11+,r2 ; count 779 75B6 C18B mov r11,r6 ; return address 780 75B8 06A0 bl @_vmbw0 ; write the string 780 75BA 7854 781 75BC 0456 b *r6 ; return 782 ;] 783 784 785 786 ;[ scan keyboard 787 75BE D820 scnkey movb @keybd,@>8374 ; set keyboard to scan 787 75C0 75E8 787 75C2 8374 788 75C4 02E0 lwpi >83e0 ; use gpl workspace 788 75C6 83E0 789 75C8 06A0 bl @>000e ; call keyboard scanning routine 789 75CA 000E 790 ; ########## added for V1.2 ########### 791 ; restore TF workspace 792 ; load a program into r0,r1,r2 & r3 as follows: 793 ; R0=LWPI 794 ; R1= 795 ; R2=BRANCH 796 ; R3= 797 ; ########## added for V1.2 ########### 798 75CC 0200 li r0,>02e0 ; lwpi instruction 798 75CE 02E0 799 75D0 C060 mov @wp,r1 ; lwpi operand 799 75D2 A012 800 75D4 0202 li r2,>0460 ; branch opcode 800 75D6 0460 801 75D8 0203 li r3,scnky1 ; operand for branch instruction 801 75DA 75DE 802 75DC 0440 b r0 803 75DE 04C7 scnky1 clr r7 804 75E0 D1E0 movb @keyin,r7 ; a new key was pressed: get ascii code 804 75E2 8375 805 75E4 0887 sra r7,8 ; move to low byte 806 75E6 045B rt ; return to caller 807 75E8 0500 keybd data >0500 ; all keys 808 ;] 809 810 811 ; miscellaneous routines 812 ;[ delay routine 813 75EA C03B delay mov *r11+,r0 814 75EC 0600 dlylop dec r0 815 75EE 16FE jne dlylop 816 75F0 045B rt 817 ;] 818 819 ;[ define cursor characters and corner edges etc 820 75F2 C18B csrdef mov r11,r6 ; save return address 821 75F4 0200 li r0,>0800 ; ascii 0 821 75F6 0800 822 75F8 0201 li r1,>fc00 ; bit pattern 822 75FA FC00 823 75FC 0202 li r2,7 ; count 823 75FE 0007 824 7600 06A0 bl @vsbwmi 824 7602 7880 825 7604 0200 li r0,>808 ; ascii 1 address 825 7606 0808 826 7608 0201 li r1,ascii1 ; source 826 760A 770B 827 760C 0202 li r2,7*8 827 760E 0038 828 7610 06A0 bl @_vmbw0 828 7612 7854 829 7614 0456 b *r6 830 ;] 831 832 833 ;[ set block status to dirty 834 7616 C18B needud mov r11,r6 835 7618 C020 mov @lstblk,r0 ; get current block 835 761A A1B4 836 761C 06A0 bl @scnblk ; locate it (blk address in r1) 836 761E 69A0 837 7620 05C1 inct r1 ; point to VDP address pointer 838 7622 C011 mov *r1,r0 ; get the VDP address 839 7624 1109 jlt skipud ; skip if already set 840 7626 0260 ori r0,>8000 ; set dirty bit 840 7628 8000 841 762A C440 mov r0,*r1 ; write it back 842 762C 0200 disupd li r0,10 ; screen address 842 762E 000A 843 7630 0201 li r1,'*'*256 ; asterisk in high byte 843 7632 2A00 844 7634 06A0 bl @_vsbw0 ; write to screen 844 7636 782C 845 7638 0456 skipud b *r6 846 ;] 847 848 ;[ display block number 849 763A C38B disblk mov r11,r14 850 763C 0202 li r2,3 850 763E 0003 851 7640 0200 li r0,6 851 7642 0006 852 7644 04C6 clr r6 853 7646 C1E0 mov @lstblk,r7 853 7648 A1B4 854 764A 020A li r10,divs 854 764C 7674 855 764E C23A dislop mov *r10+,r8 856 7650 3D88 div r8,r6 857 7652 C046 mov r6,r1 858 7654 04C6 clr r6 859 7656 0221 ai r1,48 859 7658 0030 860 765A 0A81 sla r1,8 861 765C 06A0 bl @_vsbw0 861 765E 782C 862 7660 0580 inc r0 863 7662 0602 dec r2 864 7664 16F4 jne dislop 865 7666 C047 mov r7,r1 866 7668 0221 ai r1,48 866 766A 0030 867 766C 0A81 sla r1,8 868 766E 06A0 bl @_vsbw0 868 7670 782C 869 7672 045E b *r14 870 7674 03E8 divs data 1000,100,10 870 7676 0064 870 7678 000A 871 ;] 872 873 ;[ check if 80 column mode is on or not... 874 767A C020 is80c mov @xmax,r0 ; get xmax 874 767C A02C 875 767E 0280 ci r0,80 ; compare to 80 (80-column) 875 7680 0050 876 7682 045B rt 877 ;] 878 879 7684 3020 txt0 text '0 1 2 3' 879 7686 2020 879 7688 2020 879 768A 2020 879 768C 2020 879 768E 3120 879 7690 2020 879 7692 2020 879 7694 2020 879 7696 2020 879 7698 3220 879 769A 2020 879 769C 2020 879 769E 2020 879 76A0 2020 879 76A2 33 880 76A3 3320 txt1 text '3 4 5 6' 880 76A5 2020 880 76A7 2020 880 76A9 2020 880 76AB 2020 880 76AD 3420 880 76AF 2020 880 76B1 2020 880 76B3 2020 880 76B5 2020 880 76B7 3520 880 76B9 2020 880 76BB 2020 880 76BD 2020 880 76BF 2020 880 76C1 36 881 76C2 0101 txt2 byte 1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,2,1,1,1,1,1 881 76C4 0101 881 76C6 0102 881 76C8 0101 881 76CA 0101 881 76CC 0101 881 76CE 0101 881 76D0 0102 881 76D2 0101 881 76D4 0101 881 76D6 0101 881 76D8 0101 881 76DA 0102 881 76DC 0101 881 76DE 0101 881 76E0 01 882 76E1 0101 byte 1,1,1 882 76E3 01 883 ; txt2 byte 48,1,1,1,1,2,1,1,1,1,48,1,1,1,1,2,1,1,1,1,48,1,1,1,1,2,1,1,1,1,48 884 ; byte 1,1,1 885 ; text '0----|----0----|----0----|----0---' 886 76E4 3031 rowtxt text '0123456789012345' 886 76E6 3233 886 76E8 3435 886 76EA 3637 886 76EC 3839 886 76EE 3031 886 76F0 3233 886 76F2 3435 887 76F4 426C blktxt text 'Block:' 887 76F6 6F63 887 76F8 6B3A 888 76FA 4D6F modtxt text 'Mode:' 888 76FC 6465 888 76FE 3A 889 76FF 494E instxt text 'INSERT' 889 7701 5345 889 7703 5254 890 7705 4F56 ovrtxt text 'OVER ' 890 7707 4552 890 7709 2020 891 892 ; ascii 1 data ( straight line) 893 770B 0000 ascii1 byte 0,0,0,255,255,0,0,0 ; straight line 893 770D 00FF 893 770F FF00 893 7711 0000 894 ascii2 ; byte 0,0,255,255,16,16,16,0 ; straight line with marker 895 7713 1010 byte 16,16,16,255,255,0,0,0 895 7715 10FF 895 7717 FF00 895 7719 0000 896 771B 3030 ascii3 byte >30,>30,>30,>30,>30,>30,>30,>30 ; vertical line 896 771D 3030 896 771F 3030 896 7721 3030 897 7723 0000 ascii4 byte 0,0,0,>3f,>3f,>30,>30,>30 ; top left corner 897 7725 003F 897 7727 3F30 897 7729 3030 898 772B 0000 ascii5 byte 0,0,0,>f0,>f0,>30,>30,>30 ; top right corner 898 772D 00F0 898 772F F030 898 7731 3030 899 7733 3030 ascii6 byte >30,>30,>30,>3f,>3f,0,0,0 ; bottom left corner 899 7735 303F 899 7737 3F00 899 7739 0000 900 773B 3030 ascii7 byte >30,>30,>30,>f0,>f0,0,0,0 ; bottom right corner 900 773D 30F0 900 773F F000 900 7741 0000 901 902 7743 4631 help text 'F1:Delete F2:Mode F3:Erase Line F7:Page' 902 7745 3A44 902 7747 656C 902 7749 6574 902 774B 6520 902 774D 4632 902 774F 3A4D 902 7751 6F64 902 7753 6520 902 7755 4633 902 7757 3A45 902 7759 7261 902 775B 7365 902 775D 204C 902 775F 696E 902 7761 6520 902 7763 2046 902 7765 373A 902 7767 5061 902 7769 6765 903 776B 4639 text 'F9:Exit F=:Quit ESDX:Cursor ENT:New Line' 903 776D 3A45 903 776F 7869 903 7771 7420 903 7773 463D 903 7775 3A51 903 7777 7569 903 7779 7420 903 777B 4553 903 777D 4458 903 777F 3A43 903 7781 7572 903 7783 736F 903 7785 7220 903 7787 454E 903 7789 543A 903 778B 4E65 903 778D 7720 903 778F 4C69 903 7791 6E65 904 7793 5E43 text '^C:Copy Line ^V:Paste Line ^I:Ins Line' 904 7795 3A43 904 7797 6F70 904 7799 7920 904 779B 4C69 904 779D 6E65 904 779F 2020 904 77A1 5E56 904 77A3 3A50 904 77A5 6173 904 77A7 7465 904 77A9 204C 904 77AB 696E 904 77AD 6520 904 77AF 205E 904 77B1 493A 904 77B3 496E 904 77B5 7320 904 77B7 4C69 904 77B9 6E65 905 77BB 5E44 text '^D:Del Line ^O:Prev Block ^P:Next block' 905 77BD 3A44 905 77BF 656C 905 77C1 204C 905 77C3 696E 905 77C5 6520 905 77C7 5E4F 905 77C9 3A50 905 77CB 7265 905 77CD 7620 905 77CF 426C 905 77D1 6F63 905 77D3 6B20 905 77D5 205E 905 77D7 503A 905 77D9 4E65 905 77DB 7874 905 77DD 2062 905 77DF 6C6F 905 77E1 636B 906 77E3 0000 even * * COPY 'C:\TI\Source\TurboForth\Bank1\1-12-VDP.a99' * 1 ; __ _______ _____ _ _ _ _ _ _ _ _ 2 ; \ \ / / __ \| __ \ | | | | | (_) (_) | (_) 3 ; \ \ / /| | | | |__) | | | | | |_ _| |_| |_ _ ___ ___ 4 ; \ \/ / | | | | ___/ | | | | __| | | | __| |/ _ | __| 5 ; \ / | |__| | | | |__| | |_| | | | |_| | __|__ \ 6 ; \/ |_____/|_| \____/ \__|_|_|_|\__|_|\___|___/ 7 ; VDP access utility routines 8 9 ;[ vdp single byte read 10 ; inputs: r0=address in vdp to read, r1(msb), the byte read from vdp 11 ; side effects: none 12 77E4 06C0 _vsbr swpb r0 13 77E6 D800 movb r0,@vdpa 13 77E8 8C02 14 77EA 06C0 swpb r0 15 77EC D800 movb r0,@vdpa 15 77EE 8C02 16 77F0 1000 nop 17 77F2 D060 movb @vdpr,r1 17 77F4 8800 18 77F6 045B rt 19 ;] 20 21 ;[ vdp multiple byte read 22 ; inputs: r0=vdp source address, r1=cpu ram destination address 23 ; r2=number of bytes to read 24 ; side effects: r1, r2 & r13 changed 25 77F8 C820 _vmbri mov @bank1_,@retbnk ; return to bank 1 25 77FA 606C 25 77FC A06E 26 77FE 0300 _vmbr2 limi 2 26 7800 0002 27 7802 0300 limi 0 27 7804 0000 28 ; entry point for no interrupts: 29 7806 06C0 _vmbr swpb r0 30 7808 D800 movb r0,@vdpa 30 780A 8C02 31 780C 06C0 swpb r0 32 780E D800 movb r0,@vdpa 32 7810 8C02 33 7812 1000 nop 34 7814 DC60 _vmbr1 movb @vdpr,*r1+ 34 7816 8800 35 7818 0602 dec r2 36 781A 16FC jne _vmbr1 37 781C 045B rt 38 ;] 39 40 ;[ vdp single byte write 41 ; inputs: r0=address in vdp to write to, r1(msb)=the byte to write 42 ; side effects: none 43 781E C820 _vsbw mov @bank1_,@retbnk ; return to bank 1 43 7820 606C 43 7822 A06E 44 7824 0300 limi 2 44 7826 0002 45 7828 0300 limi 0 45 782A 0000 46 ; entry point for no interrupts: 47 782C 0260 _vsbw0 ori r0,>4000 47 782E 4000 48 7830 06C0 swpb r0 49 7832 D800 movb r0,@vdpa 49 7834 8C02 50 7836 06C0 swpb r0 51 7838 D800 movb r0,@vdpa 51 783A 8C02 52 783C D801 movb r1,@vdpw 52 783E 8C00 53 7840 2820 xor @_bit1,r0 ; reset bit 1 53 7842 78B6 54 7844 045B rt 55 ;] 56 57 ;[ vdp multiple byte write 58 ; r0=destination in vdp, r1=source address in cpu ram, r2=number of bytes 59 ; side effects: r1, r2 & r13 changed 60 _vmbw 61 7846 C820 mov @bank1_,@retbnk ; return to bank 1 61 7848 606C 61 784A A06E 62 784C 0300 _vmbw2 limi 2 62 784E 0002 63 7850 0300 limi 0 63 7852 0000 64 ; entry point for no interrupts: 65 _vmbw0 ; mov r2,r2 ; check for zero length 66 ; jeq _vmbwx ; if zero then exit 67 7854 0260 ori r0,>4000 67 7856 4000 68 7858 06C0 swpb r0 69 785A D800 movb r0,@vdpa 69 785C 8C02 70 785E 06C0 swpb r0 71 7860 D800 movb r0,@vdpa 71 7862 8C02 72 7864 D831 _vmbw1 movb *r1+,@vdpw 72 7866 8C00 73 7868 0602 dec r2 74 786A 16FC jne _vmbw1 75 786C 2820 xor @_bit1,r0 ; reset bit 1 75 786E 78B6 76 7870 045B _vmbwx rt 77 ;] 78 79 ;[ vdp single byte write many 80 ; writes the same bytes multiple times to consequtive VDP address 81 ; r0=vdp destination address 82 ; r1=the byte to write (in msb) 83 ; r2=number of times to write 84 7872 C820 _vsbwm mov @bank1_,@retbnk ; return to bank 1 84 7874 606C 84 7876 A06E 85 7878 0300 _vsbwm2 limi 2 85 787A 0002 86 787C 0300 limi 0 86 787E 0000 87 ; entry point for no interrupts: 88 7880 0260 vsbwmi ori r0,>4000 ; this is a vdp write command 88 7882 4000 89 7884 06C0 swpb r0 ; low byte first 90 7886 D800 movb r0,@vdpa ; load low byte into address register 90 7888 8C02 91 788A 06C0 swpb r0 ; get high byte 92 788C D800 movb r0,@vdpa ; write high byte 92 788E 8C02 93 7890 D801 _vsbm1 movb r1,@vdpw 93 7892 8C00 94 7894 0602 dec r2 ; decrement count 95 7896 16FC jne _vsbm1 ; loop if not finished 96 7898 2820 xor @_bit1,r0 ; reset bit 1 96 789A 78B6 97 789C 045B rt ; return to caller 98 ;] 99 100 ;[ vdp write to vdp register 101 ; inputs: r0(msb)=the register to write to, r0(lsb)=the value to write 102 ; side effects: none 103 789E 0260 _vwtr ori r0,>8000 103 78A0 8000 104 78A2 06C0 swpb r0 105 78A4 D800 movb r0,@vdpa 105 78A6 8C02 106 78A8 06C0 swpb r0 107 78AA D800 movb r0,@vdpa 107 78AC 8C02 108 78AE 2820 xor @_bit0,r0 ; reset bit 0 108 78B0 78B4 109 78B2 045B rt 110 ;] 111 78B4 8000 _bit0 data >8000 ; used for re-setting bits 112 78B6 4000 _bit1 data >4000 * * COPY 'C:\TI\Source\TurboForth\Bank1\1-13-Stack.a99' * 1 ; _____ _ _ __ __ _ 2 ; / ____| | | | \ \ / / | | 3 ; | (___ | |_ __ _ ___| | __ \ \ /\ / /___ _ __ __| |___ 4 ; \___ \| __|/ _` |/ __| |/ / \ \/ \/ // _ \| '__/ _` / __| 5 ; ____) | |_| (_| | (__| < \ /\ /| (_) | | | (_| \__ \ 6 ; |_____/ \__|\__,_|\___|_|\_\ \/ \/ \___/|_| \__,_|___/ 7 ; Core words pertaining to data and return stack manipulation 8 9 ;[ PICK ( x1 x2 x3 x4 n -- x1 x2 x3 x4 x5 ) 10 ; picks the nth value from the data stack and places a copy of it on the top 11 ; of the data stack. 12 ; note: parameters start from 0. 0 PICK is equivalent to DUP. 13 ; 1 PICK is equivalent to OVER 14 78B8 C194 _pick mov *stack,r6 ; get required stack parameter number 15 78BA 0586 inc r6 ; adjust for parameter n on stack 16 78BC 0A16 sla r6,1 ; convert to byte offset 17 78BE A184 a stack,r6 ; add stack address to offset 18 78C0 C516 mov *r6,*stack ; read that address and place on stack 19 78C2 0460 pickx b @retB0 ; NEXT 19 78C4 833A 20 ;] 21 22 ;[ ROLL ( +n -- n ) 23 ; The +nth stack value, not counting +n itself is first removed and then 24 ; transferred to the top of the stack, moving the remaining values into the 25 ; vacated position. {0..the number of elements on the stack-1} 26 ; 2 ROLL is equivalent to ROT. 0 ROLL is a null operation 27 78C6 C234 _roll mov *stack+,r8 ; pop roll value in r8 28 78C8 C208 mov r8,r8 ; test for zero value 29 78CA 13FB jeq pickx ; if zero, take no action 30 78CC C284 mov stack,r10 ; copy stack pointer 31 78CE C248 mov r8,r9 ; copy roll value 32 78D0 0A18 sla r8,1 ; multiply by two, to get the offset into 33 ; the stack 34 78D2 A288 a r8,r10 ; compute stack address to start from 35 78D4 C01A mov *r10,r0 ; store stack value, this will go to TOS 36 78D6 C04A mov r10,r1 ; move everything above this stack entry 37 ; back one 38 78D8 064A dect r10 ; source 39 78DA C45A rolllp mov *r10,*r1 ; move source back one word 40 78DC 064A dect r10 41 78DE 0641 dect r1 42 78E0 0609 dec r9 ; decrement counter. finished? 43 78E2 16FB jne rolllp ; loop if not 44 78E4 C500 mov r0,*stack ; place earlier saved value to TOS 45 78E6 10ED exroll jmp pickx ; NEXT 46 ;] 47 48 ;[ DEPTH ( -- depth ) 49 ; depth is the number of 16-bit values contained in the data stack before depth 50 ; was placed on the stack. 51 78E8 C1C4 _depth mov stack,r7 ; copy address of TOS 52 78EA 05C7 inct r7 53 78EC C1A0 mov @s0,r6 ; base of stack 53 78EE A01E 54 78F0 6187 s r7,r6 ; subtract tos from base of stack 55 78F2 0816 sra r6,1 ; convert to cells 56 78F4 0644 dect stack ; new stack entry 57 78F6 C506 mov r6,*stack ; push depth 58 78F8 10E4 jmp pickx ; NEXT 59 ;] * * COPY 'C:\TI\Source\TurboForth\Bank1\1-14-File-IO.a99' * 1 ; ______ _ _ _____ ______ 2 ; | ____(_) | |_ _| / / __ \ 3 ; | |__ _| | ___ | | / / | | | 4 ; | __| | | |/ _ \ | | / /| | | | 5 ; | | | | | __/ _| |_ / / | |__| | 6 ; |_| |_|_|\___| |_____/_/ \____/ 7 ; File IO implementation 8 9 ;[ FILE ( s-addr s-len buf-addr -- ) 10 ; Builds a PAB in the buffer whose address is passed as buf_addr using the data 11 ; in the string represented by s_addr and s_len. 12 ; For example: 13 ; FBUF: PRINTER 14 ; S" PIO.CR DV80O" PRINTER FILE 15 ; The above builds a PAB in the buffer called PRINTER which references the PIO 16 ; device. Subsequent file IO words that wish to send data to the PIO shall use 17 ; the buffer name to reference it: 18 ; e.g. 19 ; PRINTER #OPEN DROP ( open PIO and drop success/fail flag) 20 ; S" HELLO WORLD" PRINTER #PUT DROP 21 ; ( write HELLO WORLD to the PIO and drop success/fail flag) 22 ; 23 ; Internally, FILE builds a PAB in the buffer which will be used by #OPEN and 24 ; all file IO words. 25 ; Word 0 of the reserved memory is used to point to the actual PAB in VDP 26 ; memory. Enough space should be reserved (with ALLOT) in the buffer to hold the 27 ; PAB and the filename. 28 ; 29 ; The string which specifies the file name and file characteristics is defined 30 ; as below. 31 ; The filename *must* come first followed by a space character. After that, the 32 ; file options can be specified in any order. 33 ; 34 ; File Options: 35 ; F=Fixed - Fixed record type 36 ; V=Variable - Variable record type 37 ; 38 ; D=Display - Display data type 39 ; L=InternaL - Internal data type 40 ; 41 ; U=Update - Update file mode 42 ; O=Output - Output file mode 43 ; I=Input - Inoput file mode 44 ; A=Append - Append file mode 45 ; 46 ; S=Sequential - Sequential file type 47 ; R=Relative - Relative file type 48 ; 49 ; Note that Internal type files require L 50 ; this is because I is used to specify INPUT 51 78FA 04C8 _file clr r8 ; zero the record length accumulator 52 78FC C2B4 mov *stack+,r10 ; pop buffer address from stack 53 ; zero the first 10 bytes of the alloted buffer 54 ; (holds the PAB data - no need to zero the filename length byte or the 55 ; file, as they'll be populated later) 56 78FE C34A mov r10,r13 ; copy buffer address 57 7900 0201 li r1,10 ; number of bytes to clear 57 7902 000A 58 7904 04FD _ficll clr *r13+ ; clear two bytes in buffer 59 7906 0641 dect r1 ; decrement counter 60 7908 16FD jne _ficll ; repeat if not finished 61 ; transfer filename to PAB... 62 790A 04C6 clr r6 ; byte ops 63 790C C024 mov @2(stack),r0 ; address of string in pad 63 790E 0002 64 7910 C04A mov r10,r1 ; copy buffer address 65 7912 0221 ai r1,12 ; point to 1st filename byte 65 7914 000C 66 7916 04C2 clr r2 ; filename length 67 7918 D1B0 tfnl movb *r0+,r6 ; get a character 68 791A 0614 dec *stack ; decrement string length 69 791C 0286 ci r6,' '*256 ; space? 69 791E 2000 70 7920 1303 jeq wfnlb ; jump if yes 71 7922 DC46 movb r6,*r1+ ; otherwise copy the byte 72 7924 0582 inc r2 ; increment length count 73 7926 10F8 jmp tfnl ; and repeat 74 ; write filename length byte... 75 7928 06C2 wfnlb swpb r2 ; get length in high byte 76 792A DA82 movb r2,@11(r10) ; move length byte into length byte position 76 792C 000B 77 ; process file options... 78 792E D1B0 fdochr movb *r0+,r6 ; get a character 79 7930 0614 dec *stack ; end of string? 80 7932 1127 jlt fdone ; jump if yes 81 7934 0286 ci r6,' '*256 ; is it a space? 81 7936 2000 82 7938 13FA jeq fdochr ; if yes then ignore it 83 793A 0286 ci r6,'9'*256 ; found a digit? 83 793C 3900 84 793E 120A jle fdodig ; if so then do digit 85 ; the option is a character. 86 ; process it against the allowed list of characters 87 7940 0207 li r7,foopts ; pointer to options list 87 7942 79A0 88 7944 020D li r13,10 ; 10 options in the list 88 7946 000A 89 7948 95C6 fnxtop cb r6,*r7 ; compare a character 90 794A 130E jeq ffopt ; jump if match detected 91 794C 0587 inc r7 ; move to next charater in list 92 794E 060D dec r13 ; decrement count 93 7950 16FB jne fnxtop ; check next option 94 7952 10ED jmp fdochr ; check next character 95 ; process numeric digit 96 7954 C248 fdodig mov r8,r9 ; copy accumulator 97 7956 0A38 sla r8,3 ; multiply accumulator by 8 98 7958 0A19 sla r9,1 ; multiply copy by 2 99 795A A209 a r9,r8 ; add them - we just did a multiply by 10 100 ; (MPY needs consecutive registers, and sometimes its just too much 101 ; like hard work, know what I mean?) 102 795C 0986 srl r6,8 ; shift byte into low byte 103 795E 0226 ai r6,-48 ; remove ascii offset 103 7960 FFD0 104 7962 A206 a r6,r8 ; add to accumulator 105 7964 04C6 clr r6 ; byte ops 106 7966 10E3 jmp fdochr ; process next character 107 ; set file option... 108 7968 0227 ffopt ai r7,-20 ; point to appropriate mask byte (the bits 108 796A FFEC 109 ; to reset) 110 796C D06A movb @3(r10),r1 ; get flag byte from PAB 110 796E 0003 111 7970 5057 szcb *r7,r1 ; reset appropriate bit(s) 112 7972 0227 ai r7,10 ; point to bits table (the bits to set) 112 7974 000A 113 7976 F057 socb *r7,r1 ; set appropriate bit(s) 114 7978 DA81 movb r1,@3(r10) ; write it back 114 797A 0003 115 797C 0227 ai r7,10 ; restore pointer 115 797E 000A 116 7980 10D6 jmp fdochr ; process next character in the string 117 7982 06C8 fdone swpb r8 ; get record length in msb 118 7984 DA88 movb r8,@6(r10) ; move it into the pab 118 7986 0006 119 ; dect stack ; pop length 120 ; dect stack ; pop address 121 7988 8D34 c *stack+,*stack+ ; pop length & address 122 798A 106E jmp fexit 123 124 798C 1010 fomask byte >10,>10 ; F & V mask 125 798E 0808 byte >08,>08 ; D & I mask 126 7990 0606 byte >06,>06,>06,>06 ; U O I & A masks 126 7992 0606 127 7994 0101 byte >01,>01 ; S & R masks 128 129 7996 0010 bitmsk byte >00,>10 ; F & V bits 130 7998 0008 byte >00,>08 ; D & I bits 131 799A 0002 byte >00,>02,>04,>06 ; U O I & A bits 131 799C 0406 132 799E 0001 byte >00,>01 ; S & R bits 133 79A0 4656 foopts text 'FVDLUOIASR' ; file options (L=internaL) 133 79A2 444C 133 79A4 554F 133 79A6 4941 133 79A8 5352 134 ;] 135 136 ;[ #OPEN ( file_addr -- t|f ) 137 ; Opens a file with the file name and attributes specified in the buffer 138 ; starting at file_addr. 139 ; The buffer (actually a PAB) is set-up with FILE. 140 ; E.g. FBUF: SERIAL 141 ; S" RS232.BA=9600 DV80SO" SERIAL FILE 142 ; SERIAL #OPEN 143 ; The above shall attempt to open the serial port for output as a Display 144 ; Variable 80 type file. 145 ; 146 ; #OPEN leaves a FALSE on the stack if the file was opened sucessfully. 147 ; If the file could not be opened then it leaves a TRUE on the stack. 148 ; This allows easy trapping with ABORT" as shown below: 149 ; SERIAL #OPEN ABORT" Could not open serial port" 150 ; 151 ; In the event of a file error, IOERR can be read to get the DSR error code. 152 ; If IOERR returns -1 (>FFFF) then this means that no free file IO slots were 153 ; found. A maximum of 3 open files is supported (2 if block files are also to 154 ; be used). Note that block files are immediately closed after they are accessed 155 ; for either reading or writing, so 3 generic file io streams are available 156 ; when no blocks files are being used. 157 158 ; find a free file slot... 159 79AA 0200 _fopen li r0,falloc ; address of file allocation table 159 79AC A1AA 160 79AE 0202 li r2,3 ; three slots 160 79B0 0003 161 79B2 C050 nxtslt mov *r0,r1 ; first slot address 162 79B4 1508 jgt foend ; if msb is not set then the slot is empty 163 79B6 05C0 inct r0 ; otherwise move to next slot address 164 79B8 0602 dec r2 ; and try it 165 79BA 16FB jne nxtslt 166 ; no free slots... sorry, no can do... 167 79BC 0720 seto @errnum ; set ioerr to -1 (no available files) 167 79BE A038 168 79C0 0714 seto *stack ; leave a TRUE on the stack 169 79C2 0460 b @retB0 169 79C4 833A 170 ; ok, the slot is free... 171 79C6 C294 foend mov *stack,r10 ; cpu pab address 172 79C8 C681 mov r1,*r10 ; store vdp address of the free PAB in word 173 ; 0 of CPU RAM PAB 174 79CA C081 mov r1,r2 ; copy the vdp address 175 79CC 0262 ori r2,>8000 ; set its most-sig bit to indicate this slot 175 79CE 8000 176 ; is in use 177 79D0 C402 mov r2,*r0 ; write it back falloc table 178 79D2 0221 ai r1,40 ; record buffer in vdp is 40 bytes after PAB 178 79D4 0028 179 79D6 CA81 mov r1,@4(r10) ; store it in bytes 2 & 3 of the PAB 179 79D8 0004 180 79DA 0221 ai r1,-40 ; restore r1 to point to PAB address in VDP 180 79DC FFD8 181 ; transfer the PAB in CPU RAM to the appropriate place in VDP 182 79DE C001 mov r1,r0 ; get in r0 for VMBW 183 79E0 C200 mov r0,r8 ; keep a copy 184 79E2 C04A mov r10,r1 ; source address 185 79E4 05C1 inct r1 ; move past word 0 in CPU PAB (vdp address 186 ; pointer) 187 79E6 0202 li r2,40 ; byte count 187 79E8 0028 188 79EA 06A0 bl @_vmbw0 ; write it to VDP 188 79EC 7854 189 79EE 0228 ai r8,9 ; adjust vdp address copy to point to 189 79F0 0009 190 ; filename length byte 191 79F2 C808 mov r8,@namptr ; store in >8356 as per DSR requirements 191 79F4 8356 192 79F6 0420 blwp @dsrlnk ; call dos 192 79F8 69DE 193 79FA 0008 data 8 ; disk op parameter, level 3 command 194 79FC 1304 jeq _foerr ; jump if an error 195 79FE 04D4 clr *stack ; set top of stack to FALSE (success) 196 7A00 04E0 clr @errnum ; clear io error 196 7A02 A038 197 7A04 1031 jmp fexit 198 ; the file could not be opened 199 7A06 0980 _foerr srl r0,8 ; move error code to lower byte 200 7A08 C800 mov r0,@errnum ; set disk io error number 200 7A0A A038 201 7A0C 0714 seto *stack ; set true flag (failure) 202 7A0E 102C jmp fexit 203 ;] 204 205 ;[ #CLOSE ( fid -- ) 206 ; closes a file 207 ; Where a file is opened thus: S" DSK1.README DV80IS" #OPEN MYFILE 208 ; the following will close the same file: MYFILE #CLOSE 209 7A10 06A0 _fclos bl @dodcmd 209 7A12 7B1A 210 7A14 0100 data close*256 211 ; now reset the pab pointer in the file allocation table... 212 ; r13 holds the vdp address of the start of the pab 213 7A16 0201 li r1,falloc ; address of file allocation table 213 7A18 A1AA 214 7A1A 0202 li r2,3 ; 3 entries in the table 214 7A1C 0003 215 7A1E C191 _fclop mov *r1,r6 ; get an entry 216 7A20 0246 andi r6,>7fff ; remove msb 216 7A22 7FFF 217 7A24 8346 c r6,r13 ; found the entry? 218 7A26 1304 jeq _fcfnd ; jump if yes 219 7A28 05C1 inct r1 ; try next word 220 7A2A 0602 dec r2 ; decrement counter 221 7A2C 16F8 jne _fclop ; repeat if not finished 222 7A2E 101C _fcxit jmp fexit 223 7A30 C44D _fcfnd mov r13,*r1 ; move address (with msb reset) back into 224 ; file allocation table 225 7A32 10FD jmp _fcxit 226 ;] 227 228 ;[ #GET ( buff_addr fid -- t|f ) 229 ; reads a line of input from the file specified by fid. 230 ; The address of an appropriately sized buffer must be supplied. 231 ; If the read is successful, the buffer is filled with the data read from the 232 ; input device, with the first cell being the length count of the data 233 ; immediately following it. 234 ; This can be converted into a address/length pair with COUNT. 235 ; Returns: 236 ; False if successful 237 ; True if not successful 238 ; This allows trapping with ABORT" as follows: 239 ; MYFILE #GET ABORT" Could not read from the file" 240 ; If the read fails, IOERR is set to the error code, otherwise it is zero'd 241 7A34 06A0 _fget bl @dodcmd ; read from disk 241 7A36 7B1A 242 7A38 0200 data read*256 243 7A3A 1312 jeq _fgerr ; jump if error 244 ; r13 holds the vdp address of the start of the pab 245 7A3C C00D mov r13,r0 ; transfer to r0 for vdp access 246 7A3E 0220 ai r0,5 ; point to character count 246 7A40 0005 247 7A42 06A0 bl @_vsbr ; read the length of the returned record 247 7A44 77E4 248 7A46 C254 mov *stack,r9 ; get cpu ram buffer address from stack 249 7A48 DE41 movb r1,*r9+ ; move length of record to the buffer 250 7A4A D081 movb r1,r2 ; copy length byte to r2 for vdp counter in 251 ; vmbr 252 7A4C 0982 srl r2,8 ; move length byte to low byte of r2 253 7A4E 1306 jeq recln0 ; jump if the record read had a length of 0 254 7A50 C00D mov r13,r0 ; start of pab 255 7A52 0220 ai r0,40 ; point to associated data buffer 255 7A54 0028 256 7A56 C049 mov r9,r1 ; cpu ram buffer address 257 7A58 06A0 bl @_vmbr ; transfer from the buffer in vdp to the 257 7A5A 7806 258 ; buffer in CPU 259 7A5C 04D4 recln0 clr *stack ; place false on stack (succeeded) 260 7A5E 1004 _fgxit jmp fexit 261 ; an error occurred 262 7A60 0980 _fgerr srl r0,8 ; move error code to lower byte 263 7A62 C800 mov r0,@errnum ; set disk io error number 263 7A64 A038 264 7A66 0714 seto *stack ; set stack to true (failed) 265 ; fall down into fexit... 266 ;] 267 268 269 270 7A68 06A0 fexit bl @rstsp ; restore code in scratchpad 270 7A6A 6AEE 271 ; (destroyed by DSR access) 272 7A6C 0460 b @retB0 272 7A6E 833A 273 274 275 276 ;[ #PUT ( buff_addr len fid - t|f ) 277 ; Places a string from buffer_addr with length len to the file represented by 278 ; fid. 279 ; Returns false if successful, else returns true. 280 ; This can be trapped with ABORT" 281 7A70 C014 _fput mov *stack,r0 ; get fid 282 7A72 C010 mov *r0,r0 ; get vdp pab address 283 7A74 C064 mov @2(stack),r1 ; get length from stack 283 7A76 0002 284 7A78 06C1 swpb r1 ; move to high byte 285 7A7A 0220 ai r0,5 ; point to length byte in pab 285 7A7C 0005 286 7A7E 06A0 bl @_vsbw0 ; write the length byte to the pab 286 7A80 782C 287 7A82 C1A0 mov @blknum,r6 ; processing a block? 287 7A84 A1B2 288 7A86 1620 jne _fpvdp ; if so then the data we want to write is 289 ; aleady in vdp 290 7A88 0220 ai r0,-3 ; else back up to point data buffer address 290 7A8A FFFD 291 7A8C C054 mov *stack,r1 ; pointer to vdp pab address in r1 292 7A8E C051 mov *r1,r1 ; get the vdp pab address 293 7A90 0221 ai r1,40 ; compute vdp buffer address(pab address+40) 293 7A92 0028 294 7A94 06A0 bl @_vsbw0 ; write msb of address 294 7A96 782C 295 7A98 0580 inc r0 ; advance vdp address 296 7A9A 06C1 swpb r1 ; get lsb 297 7A9C 06A0 bl @_vsbw0 ; write it 297 7A9E 782C 298 7AA0 C014 _fp1 mov *stack,r0 ; get vdp address of pab again 299 7AA2 C010 mov *r0,r0 ; get vdp pab address 300 7AA4 0220 ai r0,40 ; point to record buffer 300 7AA6 0028 301 7AA8 C0A4 mov @2(stack),r2 ; length 301 7AAA 0002 302 7AAC C064 mov @4(stack),r1 ; cpu source address 302 7AAE 0004 303 7AB0 06A0 bl @_vmbw0 ; write to vdp 303 7AB2 7854 304 7AB4 06A0 _fp2 bl @dodcmd 304 7AB6 7B1A 305 7AB8 0300 data write*256 306 7ABA 1303 jeq _fperr ; jump if error 307 7ABC 05C4 inct stack ; pop length 308 7ABE 04D4 clr *stack ; success 309 7AC0 10D3 _fpxit jmp fexit 310 7AC2 05C4 _fperr inct stack ; pop length 311 7AC4 0714 seto *stack ; failed 312 7AC6 10FC jmp _fpxit 313 7AC8 C014 _fpvdp mov *stack,r0 ; vdp address of pab in r0 314 7ACA C010 mov *r0,r0 ; get vdp pab address 315 7ACC 0220 ai r0,2 ; point to data buffer address 315 7ACE 0002 316 7AD0 C064 mov @-4(stack),r1 ; buffer address 316 7AD2 FFFC 317 7AD4 06A0 bl @_vsbw0 ; write msb of address 317 7AD6 782C 318 7AD8 0580 inc r0 ; advance vdp address 319 7ADA 06C1 swpb r1 ; get lsb 320 7ADC 06A0 bl @_vsbw0 ; write it 320 7ADE 782C 321 7AE0 10E9 jmp _fp2 322 ;] 323 324 ;[ #REC ( record# fid -- ) 325 ; Sets the record number for reading or writing for relative files 326 7AE2 C034 _frec mov *stack+,r0 ; get fid 327 7AE4 C010 mov *r0,r0 ; get vdp address of associated pab 328 7AE6 0220 ai r0,6 ; point to record number in vdp 328 7AE8 0006 329 7AEA D074 movb *stack+,r1 ; get record number high byte 330 7AEC 06A0 bl @_vsbw0 ; write it 330 7AEE 782C 331 7AF0 0580 inc r0 ; point to record# low byte in pab 332 7AF2 D074 movb *stack+,r1 ; get low byte of record number 333 7AF4 06A0 bl @_vsbw0 ; write it 333 7AF6 782C 334 7AF8 0460 b @retB0 334 7AFA 833A 335 ;] 336 337 338 ;[ #EOF? ( fid -- t|f ) 339 ; returns true if currently positioned at the end of the file referenced by fid 340 7AFC 06A0 _feof bl @dodcmd 340 7AFE 7B1A 341 7B00 0900 data status*256 342 7B02 C00D mov r13,r0 ; vdp address of pab to r0 343 7B04 0220 ai r0,8 ; point to screen offset byte (where status 343 7B06 0008 344 ; is stored) 345 7B08 06A0 bl @_vsbr ; read the byte 345 7B0A 77E4 346 7B0C 0241 andi r1,>0100 ; isolate bit 7 (eof bit) 346 7B0E 0100 347 7B10 0A71 sla r1,7 ; move bit to bit 0 (msb) 348 7B12 08F1 sra r1,15 ; shift it back to lsb 349 ; at this point, if bit 7 was 0 then r1 is 0000000000000000(2) (i.e. false) 350 ; if bit 7 was 1 then r1 is 1111111111111111(2) (i.e. true) 351 7B14 0644 dect stack ; make space on stack (dodcmd pops the fid) 352 7B16 C501 mov r1,*stack ; move to stack 353 7B18 10A7 jmp fexit 354 ;] 355 356 357 ;[ Do Disk Command subroutine - executes the disk command passed by the caller 358 7B1A C07B dodcmd mov *r11+,r1 ; get opcode 359 7B1C C38B mov r11,r14 ; save return address 360 7B1E C034 mov *stack+,r0 ; get pointer to cpu ram pab 361 7B20 C010 mov *r0,r0 ; get vdp address of the pab 362 7B22 C340 mov r0,r13 ; copy it (used by #CLOSE, #PUT, #EOF etc) 363 7B24 06A0 docmd1 bl @_vsbw ; write the op-code to the pab 363 7B26 781E 364 ; clear bits 0, 1 & 2 of byte 1 of the PAB... 365 7B28 0580 inc r0 ; move to byte 1 of the pab 366 7B2A 06A0 bl @_vsbr ; read it 366 7B2C 77E4 367 7B2E 0241 andi r1,>1f00 ; reset bits 0,1 & 2 367 7B30 1F00 368 7B32 06A0 bl @_vsbw ; write it back 368 7B34 781E 369 7B36 0220 ai r0,8 ; point to filename length byte 369 7B38 0008 370 7B3A C800 mov r0,@namptr ; load >8356 with pointer to name length as 370 7B3C 8356 371 ; per DSR requirements 372 ; call the DSR... 373 7B3E 0420 blwp @dsrlnk 373 7B40 69DE 374 7B42 0008 data 8 375 7B44 045E b *r14 ; return to caller 376 ;] 377 378 ; close all open files 379 ; called by abort in bank 0 380 7B46 0206 _clall li r6,6 ; offset into file allocation table, and 380 7B48 0006 381 ; also counter 382 7B4A C026 _ca1 mov @falloc(r6),r0 ; get address of PAB in vdp from file 382 7B4C A1AA 383 ; allocation table 384 7B4E C1C0 mov r0,r7 ; copy it 385 7B50 0247 andi r7,>8000 ; check 'in-use' bit 385 7B52 8000 386 7B54 130A jeq _cart ; skip if the entry in the table isn't 387 ; open/in-use 388 7B56 0240 andi r0,>7fff ; reset 'in-use' bit 388 7B58 7FFF 389 7B5A C980 mov r0,@falloc(r6) ; write it back to the file allocation table 389 7B5C A1AA 390 7B5E 020E li r14,_cart ; make #CLOSE return to us ;-) 390 7B60 7B6A 391 7B62 0201 li r1,close*256 ; close opcode for #CLOSE 391 7B64 0100 392 7B66 0460 b @docmd1 ; borrow part of the DODCMD routine to do 392 7B68 7B24 393 ; the work for us ;-) 394 7B6A 0646 _cart dect r6 ; decrement counter 395 7B6C 0286 ci r6,-2 ; finished? 395 7B6E FFFE 396 7B70 16EC jne _ca1 ; close next file if not 397 7B72 0460 b @fexit 397 7B74 7A68 * * COPY 'C:\TI\Source\TurboForth\Bank1\1-15-Initialise.a99' * 1 ; _____ _ _ _ _ _ _ _ 2 ; |_ _| (_) | (_) | (_) | | (_) 3 ; | | _ __ _| |_ _ __ _| |_ ___ __ _| |_ _ ___ _ __ 4 ; | | | '_ \| | __| |/ _` | | / __|/ _` | __| |/ _ \| '_ \ 5 ; _| |_| | | | | |_| | (_| | | \__ \ (_| | |_| | (_) | | | | 6 ; |_____|_| |_|_|\__|_|\__,_|_|_|___/\__,_|\__|_|\___/|_| |_| 7 ; this code runs at startup to bring TurboForth to life 8 9 ; general initialisation of RAM variables etc 10 11 init 12 13 7B76 C0E0 mov @sumode,r3 ; save graphics startup mode value 13 7B78 A078 14 15 7B7A 0200 li r0,>0190 ; turn the screen off while we set things up 15 7B7C 0190 16 7B7E 06A0 bl @_vwtr 16 7B80 789E 17 18 19 ;[ initialise SAMS card if fitted 20 7B82 020C li r12,>1e00 ; sams CRU base 20 7B84 1E00 21 7B86 1D00 sbo 0 ; enable access to mapper registers 22 7B88 1E01 sbz 1 ; disable mapping while we set it up 23 7B8A 0200 li r0,>4004 ; register for >2000 23 7B8C 4004 24 7B8E 0201 li r1,>f8f8 ; map bank >f8 into >2000 24 7B90 F8F8 25 7B92 CC01 mov r1,*r0+ ; do it 26 7B94 0201 li r1,>f9f9 ; map bank >f9... 26 7B96 F9F9 27 7B98 CC01 mov r1,*r0+ ; ...into >3000 28 ; now set up the banks for high memory... 29 7B9A 0200 li r0,>4014 ; register address 29 7B9C 4014 30 7B9E 0201 li r1,>fafa ; register value 30 7BA0 FAFA 31 7BA2 0202 li r2,6 ; loop count 31 7BA4 0006 32 7BA6 CC01 sams mov r1,*r0+ ; write to the register 33 7BA8 0221 ai r1,>0101 ; next register value 33 7BAA 0101 34 7BAC 0602 dec r2 ; finished? 35 7BAE 16FB jne sams ; loop if not 36 7BB0 1D01 sbo 1 ; enable mapping 37 7BB2 1E00 sbz 0 ; lock the mapper registers 38 ;] 39 40 ;[ clear variables area 41 7BB4 0200 cva li r0,>a000 ; start address 41 7BB6 A000 42 7BB8 0201 li r1,prgtop ; end address 42 7BBA A2C6 43 7BBC 04F0 clrlop clr *r0+ ; clear a word 44 7BBE 8040 c r0,r1 ; finished? 45 7BC0 16FD jne clrlop ; repeat if not 46 ;] 47 48 7BC2 C803 mov r3,@sumode ; restore start up graphics mode 48 7BC4 A078 49 7BC6 C820 mov @>83c0,@seed ; initialise random number seed 49 7BC8 83C0 49 7BCA A076 50 51 ;[ initialise block file system 52 7BCC 04E0 clr @blknum ; clear current block number 52 7BCE A1B2 53 7BD0 0200 li r0,blkvdp ; address of data list 53 7BD2 7D3E 54 7BD4 0201 li r1,blk0 ; destination 54 7BD6 A1B6 55 7BD8 0202 li r2,6 ; loop count 55 7BDA 0006 56 7BDC 04F1 init1 clr *r1+ ; clear blk indicator (0=unassigned) 57 7BDE CC70 mov *r0+,*r1+ ; load blk0 address 58 7BE0 0602 dec r2 ; finished? 59 7BE2 16FC jne init1 ; loop if not 60 ;] 61 62 ;[ set up boot file name (DSK1.BLOCKS) 63 7BE4 0200 li r0,bootfn ; address of boot filename 63 7BE6 7D4A 64 7BE8 0201 li r1,pabnln ; destination 64 7BEA A189 65 7BEC 0202 li r2,12 ; 12 bytes to copy 65 7BEE 000C 66 7BF0 DC70 bootlp movb *r0+,*r1+ ; copy a byte 67 7BF2 0602 dec r2 ; finished? 68 7BF4 16FD jne bootlp ; repeat if not 69 ;] 70 71 ;[ initialise console stuff 72 7BF6 0200 li r0,cursrd ; address of cursor delay 72 7BF8 A024 73 7BFA 04F0 clr *r0+ ; initialise cursor delay 74 7BFC 0730 seto *r0+ ; enable screen scrolling 75 7BFE 04F0 clr *r0+ ; zero current x coordinate 76 7C00 04F0 clr *r0+ ; zero current y coordinate 77 7C02 0200 li r0,>0500 ; keyboard device/scan mode 77 7C04 0500 78 7C06 D800 movb r0,@keydev ; normal (upper/lower case) key scan mode 78 7C08 A022 79 80 ; initialise vdp environment 81 ; disable interrupts, sound and sprites... 82 7C0A 0200 li r0,>8000 ; no sprite motion 82 7C0C 8000 83 ; no auto sound 84 ; no quit key 85 7C0E C800 mov r0,@>83c2 ; see page 4 smart programmer 85 7C10 83C2 86 ; oct 86-vol 2 issue 5 87 ;] 88 89 ;[ load character sets... 90 91 ; initialise control characters to something visible 92 ; we do this by writing the TF logo to ALL 256 characters 93 ; later we define the capital and lower case character sets. 94 7C12 0200 cclop li r0,>800 ; address of ascii 0 94 7C14 0800 95 7C16 0203 li r3,123 ; number of characters to write 95 7C18 007B 96 7C1A 0201 cclop1 li r1,logo ; source (TF logo character) 96 7C1C 7E26 97 7C1E 0202 li r2,8 ; bytes to copy 97 7C20 0008 98 7C22 06A0 bl @_vmbw0 ; write them 98 7C24 7854 99 7C26 0220 ai r0,8 ; next character 99 7C28 0008 100 7C2A 0603 dec r3 ; decrement count 101 7C2C 16F6 jne cclop1 ; loop if not finished 102 103 ; load small ascii character set 104 7C2E 0200 li r0,>08ff ; vdp address of upper case A 104 7C30 08FF 105 7C32 C800 mov r0,@fac ; vdp address for small capitals 105 7C34 834A 106 7C36 0420 blwp @gpllnk ; load small capitals character set 106 7C38 7E54 107 7C3A 0018 data >0018 ; gpl command code 108 109 ; load true lower case characters 110 7C3C 0200 li r0,>b08 ; vdp address of lower case a 110 7C3E 0B08 111 7C40 0201 li r1,lowcas ; source 111 7C42 7D56 112 7C44 0202 li r2,26*8 ; count 112 7C46 00D0 113 7C48 06A0 bl @_vmbw0 ; write true lower case char set 113 7C4A 7854 114 115 ; load curly { | } ~ characters, which for some reason are not loaded by the 116 ; console 117 7C4C 0200 li r0,>bd8 ; vdp destination address 117 7C4E 0BD8 118 7C50 0201 li r1,lbrace ; source 118 7C52 7E2E 119 7C54 0202 li r2,4*8 ; count 119 7C56 0020 120 7C58 06A0 bl @_vmbw0 120 7C5A 7854 121 122 ; load slashed 0 123 7C5C 0200 li r0,>981 123 7C5E 0981 124 7C60 0201 li r1,zerochr 124 7C62 7E4E 125 7C64 0202 li r2,6 125 7C66 0006 126 7C68 06A0 bl @_vmbw0 126 7C6A 7854 127 128 ; initialise inverse characters 129 ; ascii codes 144 to 218 are inverse of 48 to 122 130 7C6C 0205 doinv li r5,>900 ; vdp source 130 7C6E 0900 131 7C70 0206 li r6,>c00 ; vdp destination 131 7C72 0C00 132 7C74 0204 li r4,728 ; count 132 7C76 02D8 133 7C78 C005 invlop mov r5,r0 ; get source address in r0 for VDP ops 134 7C7A 06A0 bl @_vsbr ; go read the vdp data (result in R1) 134 7C7C 77E4 135 7C7E 0541 inv r1 ; invert it 136 7C80 C006 mov r6,r0 ; load destination address 137 7C82 06A0 bl @_vsbw0 ; write r1 to destination address 137 7C84 782C 138 7C86 0585 inc r5 ; advance source address 139 7C88 0586 inc r6 ; advance destination address 140 7C8A 0604 dec r4 ; decrement counter 141 7C8C 16F5 jne invlop ; loop until finished 142 143 7C8E 06A0 bl @csrdef ; define cursor and edge characters 143 7C90 75F2 144 ; (see 1-11-Editor.a99) 145 146 ;] 147 148 ;[ Copy PAD routines into PAD RAM 149 7C92 06A0 bl @rstsp ; use the restore routine in 1-06-Blocks.a99 149 7C94 6AEE 150 ;] 151 152 ;[ general initialisation - initialised from an address/data list 153 7C96 0200 li r0,adrlst ; pointer to address/data table 153 7C98 7CBA 154 7C9A 0202 li r2,33 ; number of items to load 154 7C9C 0021 155 7C9E C070 nxtdat mov *r0+,r1 ; get address to load 156 7CA0 C470 mov *r0+,*r1 ; load the address with data 157 7CA2 0602 dec r2 ; finished? 158 7CA4 16FC jne nxtdat ; loop if not 159 ;] 160 161 ;[ set up data and return stacks... 162 7CA6 0204 li stack,dstack ; data stack pointer 162 7CA8 A2C6 163 7CAA 0205 li rstack,retstk ; return stack pointer 163 7CAC A28A 164 165 7CAE 04E0 clr @spcsvc ; clear speech service routine pointer 165 7CB0 A03E 166 167 7CB2 020C li r12,afteri ; force return point in bank 0 167 7CB4 607A 168 7CB6 0460 b @retB0 ; return to caller in bank 0 168 7CB8 833A 169 ;] 170 171 ;[ initialisation data 172 adrlst 173 7CBA A05C data base, 10 ; default number base 173 7CBC 000A 174 7CBE A02C data xmax, 40 ; 40 column line 174 7CC0 0028 175 7CC2 A02E data ymax, 24 ; 24 rows 175 7CC4 0018 176 7CC6 A044 data latest, lastwd ; last word in the dictionary 176 7CC8 7F10 177 7CCA A046 data here, prgtop ; start of compiled code area 177 7CCC A2C6 178 7CCE A01E data s0, dstack ; start of data stack 178 7CD0 A2C6 179 7CD2 A020 data rs0, retstk ; start of return stack 179 7CD4 A28A 180 7CD6 A01A data ffailm, >2000 ; first free address in low memory 180 7CD8 2000 181 7CDA A01C data ffaihm, himem ; first free address in high memory 181 7CDC A2C6 182 7CDE FFFC data >fffc, wkspc ; pointer to workspace for load-interrupt 182 7CE0 8300 183 7CE2 FFFE data >fffe, startB0 ; pointer to start of code for load-interrupt 183 7CE4 606E 184 7CE6 A06E data retbnk, >6002 ; return to bank 1 184 7CE8 6002 185 7CEA A04A data tibsiz, 80 ; 80 characters input buffer length 185 7CEC 0050 186 7CEE A1CE data tibadr, tib ; location of input buffer 186 7CF0 3420 187 ; (defined in 0-23-System.a99) 188 7CF2 A04E data doboot, 1 ; booting flag (default:on) 188 7CF4 0001 189 7CF6 A050 data sdelim, '"'*256 ; default string delimiter character 189 7CF8 2200 190 7CFA A1B0 data totblk, blocks ; default number of block buffers available 190 7CFC 0006 191 7CFE A000 data intvec, intgo ; default vector for interpret 191 7D00 730A 192 7D02 A002 data blkvec, block2 ; default vector for block 192 7D04 7BA4 193 7D06 A004 data numvec, numbr1 ; default vector for number 193 7D08 6B82 194 7D0A A006 data fndvec, vfind ; default vector for find 194 7D0C 6AE4 195 7D0E A1AA data falloc, f1pab ; address of pab for 1st file 195 7D10 1800 196 7D12 A1AC data falloc+2, f2pab ; address of pab for 2nd file 196 7D14 1928 197 7D16 A1AE data falloc+4, f3pab ; address of pab for 3rd file 197 7D18 1A50 198 7D1A A00E data gplvec, gpllnk ; pointer to gpllnk 198 7D1C 7E54 199 7D1E A010 data padvec, rstsp ; pointer to scratchpad code in bank 1 199 7D20 6AEE 200 7D22 A066 data _WARN, -1 ; default value for warn 200 7D24 FFFF 201 7D26 83C4 data isr, runisr ; pointer to isr launcher in pad 201 7D28 834C 202 7D2A A012 data wp, >8300 ; initial workspace pointer 202 7D2C 8300 203 7D2E A014 data pnext, _next ; address of next 203 7D30 8326 204 7D32 A00C data dsrvec, dsrlnk ; load pointer to DSRLNK vector 204 7D34 69DE 205 7D36 A016 data pdocon, docon ; load pointer to DOCON's executable code 205 7D38 7008 206 7D3A A018 data pcreate, crtime ; load pointer to CREATE's executable code 206 7D3C 6FA4 207 208 ; VDP block buffer addresses for disk block IO... 209 blkvdp 210 7D3E 3020 data bufadd+>1400 ; vdp address of buffer 0 211 7D40 2C20 data bufadd+>1000 ; vdp address of buffer 1 212 7D42 2820 data bufadd+>c00 ; vdp address of buffer 2 213 7D44 2420 data bufadd+>800 ; vdp address of buffer 3 214 7D46 2020 data bufadd+>400 ; vdp address of buffer 4 215 7D48 1C20 data bufadd ; vdp address of buffer 5 216 ; (bufadd defined in 0-23-System.a99) 217 218 ; boot filename - system looks for this file on startup and attempts to load 219 ; from block 1 if found. holding any key supresses this behaviour ala XB. 220 7D4A 0B bootfn byte 11 ; length 221 7D4B 4453 text 'DSK1.BLOCKS' ; file to boot from 221 7D4D 4B31 221 7D4F 2E42 221 7D51 4C4F 221 7D53 434B 221 7D55 53 222 even 223 224 lowcas 225 ; funnelweb editor lower case font: 226 7D56 0000 data >0000,>3808,>7848,>7c00 226 7D58 3808 226 7D5A 7848 226 7D5C 7C00 227 7D5E 4040 data >4040,>7844,>4444,>7800 227 7D60 7844 227 7D62 4444 227 7D64 7800 228 7D66 0000 data >0000,>3844,>4040,>3c00 228 7D68 3844 228 7D6A 4040 228 7D6C 3C00 229 7D6E 0404 data >0404,>3c44,>4444,>3c00 229 7D70 3C44 229 7D72 4444 229 7D74 3C00 230 7D76 0000 data >0000,>3844,>7c40,>3c00 230 7D78 3844 230 7D7A 7C40 230 7D7C 3C00 231 7D7E 1C20 data >1c20,>7820,>2020,>2000 231 7D80 7820 231 7D82 2020 231 7D84 2000 232 7D86 0000 data >0000,>3c44,>443c,>0438 232 7D88 3C44 232 7D8A 443C 232 7D8C 0438 233 7D8E 4040 data >4040,>7844,>4444,>4400 233 7D90 7844 233 7D92 4444 233 7D94 4400 234 7D96 1000 data >1000,>3010,>1010,>3800 234 7D98 3010 234 7D9A 1010 234 7D9C 3800 235 7D9E 0800 data >0800,>1808,>0808,>4830 235 7DA0 1808 235 7DA2 0808 235 7DA4 4830 236 7DA6 2020 data >2020,>2428,>3028,>2400 236 7DA8 2428 236 7DAA 3028 236 7DAC 2400 237 7DAE 3010 data >3010,>1010,>1010,>3800 237 7DB0 1010 237 7DB2 1010 237 7DB4 3800 238 7DB6 0000 data >0000,>7854,>5454,>5400 238 7DB8 7854 238 7DBA 5454 238 7DBC 5400 239 7DBE 0000 data >0000,>7844,>4444,>4400 239 7DC0 7844 239 7DC2 4444 239 7DC4 4400 240 7DC6 0000 data >0000,>3844,>4444,>3800 240 7DC8 3844 240 7DCA 4444 240 7DCC 3800 241 7DCE 0000 data >0000,>7844,>4478,>4040 241 7DD0 7844 241 7DD2 4478 241 7DD4 4040 242 7DD6 0000 data >0000,>3c44,>443c,>0404 242 7DD8 3C44 242 7DDA 443C 242 7DDC 0404 243 7DDE 0000 data >0000,>5c60,>4040,>4000 243 7DE0 5C60 243 7DE2 4040 243 7DE4 4000 244 7DE6 0000 data >0000,>3c40,>3804,>7800 244 7DE8 3C40 244 7DEA 3804 244 7DEC 7800 245 7DEE 0020 data >0020,>7820,>2024,>1800 245 7DF0 7820 245 7DF2 2024 245 7DF4 1800 246 7DF6 0000 data >0000,>4444,>4444,>3c00 246 7DF8 4444 246 7DFA 4444 246 7DFC 3C00 247 7DFE 0000 data >0000,>4444,>2828,>1000 247 7E00 4444 247 7E02 2828 247 7E04 1000 248 7E06 0000 data >0000,>4444,>5454,>2800 248 7E08 4444 248 7E0A 5454 248 7E0C 2800 249 7E0E 0000 data >0000,>4428,>1028,>4400 249 7E10 4428 249 7E12 1028 249 7E14 4400 250 7E16 0000 data >0000,>4424,>1808,>1020 250 7E18 4424 250 7E1A 1808 250 7E1C 1020 251 7E1E 0000 data >0000,>7c08,>1020,>7c00 251 7E20 7C08 251 7E22 1020 251 7E24 7C00 252 253 7E26 00E0 logo data >00e0,>405c,>5018,>1000 ; represents control characters 253 7E28 405C 253 7E2A 5018 253 7E2C 1000 254 7E2E 0018 lbrace data >0018,>2020,>4020,>2018 ; left curly brace (123) { 254 7E30 2020 254 7E32 4020 254 7E34 2018 255 7E36 0010 data >0010,>1010,>0010,>1010 ; bar character (124) | 255 7E38 1010 255 7E3A 0010 255 7E3C 1010 256 7E3E 0030 data >0030,>0808,>0408,>0830 ; right curly brace (125) } 256 7E40 0808 256 7E42 0408 256 7E44 0830 257 7E46 0000 data >0000,>2054,>0800,>0000 ; tilde (126) ~ 257 7E48 2054 257 7E4A 0800 257 7E4C 0000 258 7E4E 4C54 zerochr data >4c54,>5454,>6438 ; slashed zero 258 7E50 5454 258 7E52 6438 259 ;] 260 261 ;[ GPLLNK 262 ; This routine is based on the routine published in the July 1986 edition of 263 ; Smart Programmer. Modified by yours truly to allow it be executed from ROM. 264 0000 83E0 gplws equ >83e0 ; GPL workspace 265 0000 83E8 gr4 equ gplws+8 ; GPL R4 266 0000 83EC gr6 equ gplws+12 ; GPL R6 267 0000 8373 stkpnt equ >8373 ; GPL stack pointer 268 0000 0060 ldgadd equ >60 ; load and execute grom address entry point 269 0000 200E xtab27 equ >200e ; low mem XML table location 27 270 0000 166C getstk equ >166c 271 272 ; cpu register data - this data is copied into >200e onwards, so that it sits 273 ; in R7 onwards 274 7E54 2000 gpllnk data glnkws ; [mapped to R7] set up BLWP vectors 275 7E56 7E5E data glink1 ; [mapped to R8] 276 7E58 7E90 rtnad data xmlrtn ; [mapped to R9] 277 7E5A 176C gxmlad data >176c ; [mapped to R10] GROM address for GPL XML 0F27 278 ; opcode 279 7E5C 0050 data >50 ; [mapped to R11] Initialised to >50 where 280 ; PUTSTK address resides 281 282 ; this routine runs in it's own workspace, starting at >2000 283 0000 2000 glnkws equ >2000 ; GPLLNKs workspace of which only registers 284 ; R7 thru R15 are used 285 286 7E5E 0200 glink1 li r0,gpllnk ; we need to copy the cpu register data 286 7E60 7E54 287 7E62 0201 li r1,>200e ; (above) to RAM. R0=Source, R1=Destination 287 7E64 200E 288 7E66 CC70 gpllop mov *r0+,*r1+ ; copy the data above into r7 289 7E68 CC70 mov *r0+,*r1+ ; copy the data above into r8 290 7E6A CC70 mov *r0+,*r1+ ; copy the data above into r9 291 7E6C CC70 mov *r0+,*r1+ ; copy the data above into r10 292 7E6E CC70 mov *r0+,*r1+ ; copy the data above into r11 293 7E70 C81B mov *r11,@gr4 ; put PUTSTK address into R4 of GPL WS 293 7E72 83E8 294 7E74 C83E mov *r14+,@gr6 ; put GPL routine address in r6 of GPL WS 294 7E76 83EC 295 7E78 C809 mov r9,@xtab27 ; put XMLRTN address into >200e 295 7E7A 200E 296 7E7C 02E0 lwpi gplws ; load GPL workspace 296 7E7E 83E0 297 7E80 0694 bl *r4 ; save current GROM address on stack 298 7E82 C920 mov @gxmlad,@>8302(r4) ; push GPL XML address on stack for GPL ret 298 7E84 7E5A 298 7E86 8302 299 7E88 05E0 inct @stkpnt ; adjust the stack pointer 299 7E8A 8373 300 7E8C 0460 b @ldgadd ; execute our GPL routine 300 7E8E 0060 301 7E90 C120 xmlrtn mov @getstk,r4 ; get GETSTK pointer 301 7E92 166C 302 7E94 0694 bl *r4 ; restore GROM address off the stack 303 7E96 02E0 lwpi glnkws ; load our ws 303 7E98 2000 304 7E9A 0380 rtwp ; all done - return to caller 305 ;] 306 307 ;[ Check boot device routine 308 ; this routine is called from 0-01-Startup.a99 to modify the disk boot device 309 ; from DSK1 to DSKx where x is the ascii character of the key held down during 310 ; cartridge boot-up 311 7E9C C014 _cboot mov *stack,r0 ; get key-code from the stack 312 7E9E 0280 ci r0,13 ; enter pressed? 312 7EA0 000D 313 7EA2 1602 jne cboot1 ; jump if not 314 7EA4 04D4 clr *stack ; enter was pressed. zero top of stack to 315 ; supress auto loading. 316 7EA6 1006 jmp cbootx ; return 317 7EA8 0280 cboot1 ci r0,-1 ; nothing pressed? 317 7EAA FFFF 318 7EAC 1303 jeq cbootx ; if nothing pressed then exit routine 319 7EAE 0A80 sla r0,8 ; otherwise move key code move to high byte 320 7EB0 D800 movb r0,@pabfil+3 ; place the digit in cpu PAB 320 7EB2 A18D 321 7EB4 0460 cbootx b @retB0 321 7EB6 833A 322 ;] 323 324 ;[ 325 ; *************************************************** 326 ; The following routines are copied to PAD on startup 327 ; *************************************************** 328 ;DOCOL 329 ; Executes a high-level colon definition. 330 ; Saves return address on the return stack, loads new execution thread and 331 ; drops down into NEXT to begin executing the thread. 332 ; Note: These three routines are actually copied to scratchpad ram for extra 333 ; speed. See the equates below for their addresses in PAD 334 335 0000 8320 docol equ >8320 ; address of this routine in PAD 336 7EB8 0645 toRAM dect rstack ; make space on return stack 337 7EBA C543 mov pc,*rstack ; save PC to return stack 338 7EBC C0C6 mov r6,pc ; place in PC and drop down to NEXT 339 340 ;NEXT 341 ; loads the next CFA and branches to the address in the CFA. 342 0000 8326 _next equ docol+6 ; 8326 address of this routine in PAD 343 7EBE C1B3 mov *pc+,r6 ; get CFA in r6 344 7EC0 C1F6 mov *r6+,r7 ; get contents of CFA 345 7EC2 0457 b *r7 ; execute it 346 347 ;EXIT 348 ; exits from a FORTH high level word (i.e. a word entered with DOCOL) 349 0000 832C exit equ _next+6 ; 832c address of this routine in PAD 350 7EC4 832E data exit+2 ; called by NEXT, so needs a pointer 351 7EC6 C0F5 mov *rstack+,pc ; place saved PC into PC & pop return stack 352 7EC8 045C b *next ; do next instruction 353 354 ;BANK1 355 ; routine to perform a bank switch and branch 356 0000 8332 bank1 equ exit+6 ; 8332 address of this routine in PAD 357 7ECA C2DB mov *r11,r11 ; get branch address 358 7ECC 04E0 clr @>6000 ; select bank 1 358 7ECE 6000 359 7ED0 045B b *r11 ; branch to the desired address 360 361 ;RETB0 362 ; routine to return to a calling routine in bank 0 363 0000 833A retB0 equ bank1+8 ; 833a address of this routine in PAD 364 7ED2 04E0 cpypnt clr @>6002 ; select bank 0 364 7ED4 6002 365 7ED6 045C b *next 366 367 368 ; speech synth status routine 369 0000 8340 spstat equ retB0+6 370 7ED8 D820 movb @spchrd,@spdata ; 8340 move data from synth to memory 370 7EDA 9000 370 7EDC 834A 371 7EDE 0BC0 src r0,12 ; wait 12uS - see editor assembler page 349, 372 ; paragraph 5. 373 7EE0 045B rt 374 ; the speech synth status will be placed into the following memory location: 375 0000 834A spdata equ spstat+10 376 7EE2 1000 nop ; 834a dummy space for spdata 377 378 ; routine to call the ISRs in bank1 (actually located 'in' FAC) 379 0000 834C runisr equ spdata+2 380 7EE4 04E0 clr @>6000 ; 834c select bank 1 380 7EE6 6000 381 7EE8 0460 b @isrdes ; jump to ISR despatch handler in bank 1 381 7EEA 607A 382 383 ; ISR return code - select appropriate bank and resume 384 0000 8354 isrxit equ runisr+8 385 7EEC C020 mov @retbnk,r0 ; 8354 get bank to return to 385 7EEE A06E 386 7EF0 04D0 clr *r0 ; select that bank 387 7EF2 045A b *r10 ; return to console ISR routine in console 388 ; ROM 389 390 ; SWAP - runs from high-speed RAM 391 0000 835C _swap equ isrxit+8 392 7EF4 C1D4 mov *stack,r7 ; 835c save TOS 393 7EF6 C524 mov @2(stack),*stack ; move TOS-1 to TOS 393 7EF8 0002 394 7EFA C907 mov r7,@2(stack) ; move previous TOS to TOS-1 394 7EFC 0002 395 7EFE 045C b *next ; 396 397 ; LIT - runs from high-speed RAM 398 0000 8368 _lit equ _swap+12 399 7F00 0644 dect stack ; 8368 create space on the data stack 400 7F02 C533 mov *pc+,*stack ; push in-line number to data stack 401 7F04 045C b *next 402 403 ; DUP - runs from high-speed RAM 404 0000 8382 _dup equ _lit+26 ; >8382 ; (jump over TI reserved PAD locations) 405 7F06 0644 __dup dect stack ; 8382 create stack entry 406 7F08 C524 mov @2(stack),*stack ; mov word @ TOS+1 to TOS 406 7F0A 0002 407 7F0C 045C b *next ; 408 409 ; DROP - runs from high-speed RAM 410 0000 838A _drop equ _dup+8 ; >8388 411 7F0E 05C4 inct stack ; 8388 pop stack 412 7F10 045C b *next ; return 413 414 ; OVER - runs from high-speed RAM 415 0000 838E _over equ _drop+4 ; >838c 416 7F12 0644 dect stack ; 838c move forward one stack position 417 7F14 C524 mov @4(stack),*stack ; copy x1 to TOS 417 7F16 0004 418 7F18 045C b *next ; 419 420 ; 1+ - runs from high-speed RAM 421 0000 8396 _plus1 equ _over+8 ; >8394 422 7F1A 0594 inc *stack ; 8394 increment contents of data stack by 1 423 7F1C 045C b *next ; 424 425 ; 2+ - runs from high-speed RAM 426 0000 839A _plus2 equ _plus1+4 ; 427 7F1E 05D4 inct *stack ; 839c increment contents of data stack by 2 428 7F20 045C b *next ; 429 430 ; 2- - runs from high-speed RAM 431 0000 839E _sub2 equ _plus2+4 ; 432 7F22 0654 dect *stack ; 83a0 decrement contents of data stack by 2 433 7F24 045C b *next ; 434 435 ; + - runs from high-speed RAM 436 0000 83A2 _add equ _sub2+4 ; 437 7F26 A534 a *stack+,*stack ; 83a4 pop tos and add to datastack-1 438 7F28 045C b *next ; 439 440 ; - - runs from high-speed RAM 441 0000 83A6 _sub equ _add+4 ; 442 7F2A 6534 s *stack+,*stack ; 83a8 pop tos and subtract from datastack-1 443 7F2C 045C b *next ; 444 445 ; * - runs from high-speed RAM 446 0000 83AA _mul equ _sub+4 ; 447 7F2E C224 mov @2(stack),r8 ; 83ac word under TOS into r8 447 7F30 0002 448 7F32 3A34 mpy *stack+,r8 ; pop tos and multiply by r8 449 ; (lsw of result in r9) 450 7F34 C509 mov r9,*stack ; place result onto data stack 451 7F36 045C b *next 452 453 ; 0BRANCH 454 0000 83B4 _zbrnch equ _mul+10 455 ; at entry, R3 is pointing at the branch address... 456 7F38 C034 mov *stack+,r0 ; 83b6 test and pop flag 457 7F3A 1602 jne zbq ; if NOT zero, remove from stack and quit 458 7F3C C0D3 mov *pc,pc ; stack was zero, we're taking the jump... 459 ; move address to instruction pointer 460 7F3E 045C b *next 461 7F40 05C3 zbq inct pc ; otherwise move past address 462 7F42 045C b *next 463 padend ; end of secod source block 464 ; end of copy to PAD section 465 ;] * * COPY 'C:\TI\Source\TurboForth\Bank1\1-16-End.a99' * 1 ; _______ _ _ ______ ______ _ _ _____ _ 2 ; |__ __| | | | ____| | ____| \ | | __ \ | | 3 ; | | | |__| | |__ | |__ | \| | | | | | | 4 ; | | | __ | __| | __| | . ` | | | | | | 5 ; | | | | | | |____ | |____| |\ | |__| | |_| 6 ; |_| |_| |_|______| |______|_| \_|_____/ (_) 7 8 even 9 7F44 5368 text 'Sheila' 9 7F46 6569 9 7F48 6C61 10 even 11 0000 7F4A endB1 equ $ ; end of bank 1 marker 12 7F4A 0000 end ; so long, and thanks for all the fish 12